Version 2.17.0-86.0.dev
Merge commit 'c9f223c5bd92762266423f3f6756595e7fed8cc5' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95cb252..fec38ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -42,14 +42,14 @@
was intended for use only by build systems like bazel, `build_web_compilers`
and `flutter_tools`. The functionality remains available for those systems,
but it is no longer exposed as a command-line tool in the SDK.
- Please share any concerns in the
+ Please share any concerns in the
[breaking change tracking issue](https://github.com/dart-lang/sdk/issues/46100).
- **Breaking Change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
The standalone `dartdoc` tool has been removed as
previously announced. Its replacement is the `dart doc` command.
-## 2.16.0
+## 2.16.0 - 2022-02-03
### Core libraries
@@ -118,7 +118,7 @@
Updated the Linter to `1.18.0`, which includes changes that
- extends `camel_case_types` to cover enums.
-- fixes `no_leading_underscores_for_local_identifiers` to not
+- fixes `no_leading_underscores_for_local_identifiers` to not
mis-flag field formal parameters with default values.
- fixes `prefer_function_declarations_over_variables` to not
mis-flag non-final fields.
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
index d35a1b0..36b560b 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
@@ -24,21 +24,14 @@
/// This api is only available to the declaration and definition phases of
/// macro expansion.
abstract class TypeResolver {
- /// Resolves [typeAnnotation] to a [StaticType].
+ /// Instantiates a new [StaticType] for a given [type] annotation.
///
- /// Throws an error if the type annotation cannot be resolved. This should
- /// only happen in the case of incomplete or invalid programs, but macros
- /// may be asked to run in this state during the development cycle. It is
- /// helpful for users if macros provide a best effort implementation in that
- /// case or handle the error in a useful way.
- Future<StaticType> instantiateType(covariant TypeAnnotation typeAnnotation);
-
- /// Instantiates a new [StaticType] for a given [code] expression, which must
- /// be a type expression.
- ///
- /// All type identifiers in [code] must be instances of [Identifier] and not
- /// bare strings.
- Future<StaticType> instantiateCode(ExpressionCode code);
+ /// Throws an error if the [type] object contains [Identifier]s which cannot
+ /// be resolved. This should only happen in the case of incomplete or invalid
+ /// programs, but macros may be asked to run in this state during the
+ /// development cycle. It may be helpful for users if macros provide a best
+ /// effort implementation in that case or handle the error in a useful way.
+ Future<StaticType> resolve(TypeAnnotationCode type);
}
/// The api used to introspect on a [ClassDeclaration].
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
index e7af1bd..6563aef 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
@@ -32,18 +32,6 @@
DeclarationCode.fromParts(List<Object> parts) : super.fromParts(parts);
}
-/// A piece of code representing a syntactically valid element.
-///
-/// Should not include any trailing commas,
-class ElementCode extends Code {
- @override
- CodeKind get kind => CodeKind.element;
-
- ElementCode.fromString(String code) : super.fromString(code);
-
- ElementCode.fromParts(List<Object> parts) : super.fromParts(parts);
-}
-
/// A piece of code representing a syntactically valid expression.
class ExpressionCode extends Code {
@override
@@ -69,67 +57,200 @@
FunctionBodyCode.fromParts(List<Object> parts) : super.fromParts(parts);
}
-/// A piece of code identifying a named argument.
-///
-/// This should not include any trailing commas.
-class NamedArgumentCode extends Code {
- @override
- CodeKind get kind => CodeKind.namedArgument;
-
- NamedArgumentCode.fromString(String code) : super.fromString(code);
-
- NamedArgumentCode.fromParts(List<Object> parts) : super.fromParts(parts);
-}
-
/// A piece of code identifying a syntactically valid function parameter.
///
-/// This should not include any trailing commas, but may include modifiers
-/// such as `required`, and default values.
+/// There is no distinction here made between named and positional parameters.
///
-/// There is no distinction here made between named and positional parameters,
-/// nor between optional or required parameters. It is the job of the user to
-/// construct and combine these together in a way that creates valid parameter
-/// lists.
-class ParameterCode extends Code {
+/// It is the job of the user to construct and combine these together in a way
+/// that creates valid parameter lists.
+class ParameterCode implements Code {
+ final Code? defaultValue;
+ final List<String> keywords;
+ final String name;
+ final TypeAnnotationCode? type;
+
@override
CodeKind get kind => CodeKind.parameter;
- ParameterCode.fromString(String code) : super.fromString(code);
-
- ParameterCode.fromParts(List<Object> parts) : super.fromParts(parts);
-}
-
-/// A piece of code representing a syntactically valid statement.
-///
-/// Should always end with a semicolon.
-class StatementCode extends Code {
@override
- CodeKind get kind => CodeKind.statement;
+ List<Object> get parts => [
+ if (keywords.isNotEmpty) ...[
+ ...keywords.joinAsCode(' '),
+ ' ',
+ ],
+ if (type != null) ...[
+ type!,
+ ' ',
+ ],
+ name,
+ if (defaultValue != null) ...[
+ ' = ',
+ defaultValue!,
+ ]
+ ];
- StatementCode.fromString(String code) : super.fromString(code);
-
- StatementCode.fromParts(List<Object> parts) : super.fromParts(parts);
+ ParameterCode({
+ this.defaultValue,
+ this.keywords = const [],
+ required this.name,
+ this.type,
+ });
}
-extension Join<T extends Code> on List<T> {
+/// A piece of code representing a type annotation.
+abstract class TypeAnnotationCode implements Code {
+ /// Returns a [TypeAnnotationCode] object which is a non-nullable version
+ /// of this one.
+ ///
+ /// Returns the current instance if it is already non-nullable.
+ TypeAnnotationCode get asNonNullable => this;
+
+ /// Returns a [TypeAnnotationCode] object which is a non-nullable version
+ /// of this one.
+ ///
+ /// Returns the current instance if it is already nullable.
+ NullableTypeAnnotationCode get asNullable =>
+ new NullableTypeAnnotationCode(this);
+
+ /// Whether or not this type is nullable.
+ bool get isNullable => false;
+}
+
+/// The nullable version of an underlying type annotation.
+class NullableTypeAnnotationCode implements TypeAnnotationCode {
+ /// The underlying type that is being made nullable.
+ TypeAnnotationCode underlyingType;
+
+ @override
+ CodeKind get kind => CodeKind.nullableTypeAnnotation;
+
+ @override
+ List<Object> get parts => [...underlyingType.parts, '?'];
+
+ /// Creates a nullable [underlyingType] annotation.
+ ///
+ /// If [underlyingType] is a NullableTypeAnnotationCode, returns that
+ /// same type.
+ NullableTypeAnnotationCode(this.underlyingType);
+
+ @override
+ TypeAnnotationCode get asNonNullable => underlyingType;
+
+ @override
+ NullableTypeAnnotationCode get asNullable => this;
+
+ @override
+ bool get isNullable => true;
+}
+
+/// A piece of code representing a reference to a named type.
+class NamedTypeAnnotationCode extends TypeAnnotationCode {
+ final Identifier name;
+
+ final List<TypeAnnotationCode> typeArguments;
+
+ @override
+ CodeKind get kind => CodeKind.namedTypeAnnotation;
+
+ @override
+ List<Object> get parts => [
+ name,
+ if (typeArguments.isNotEmpty) ...[
+ '<',
+ ...typeArguments.joinAsCode(', '),
+ '>',
+ ],
+ ];
+
+ NamedTypeAnnotationCode({required this.name, this.typeArguments = const []});
+}
+
+/// A piece of code representing a function type annotation.
+class FunctionTypeAnnotationCode extends TypeAnnotationCode {
+ final List<ParameterCode> namedParameters;
+
+ final List<ParameterCode> positionalParameters;
+
+ final TypeAnnotationCode? returnType;
+
+ final List<TypeParameterCode> typeParameters;
+
+ @override
+ CodeKind get kind => CodeKind.functionTypeAnnotation;
+
+ @override
+ List<Object> get parts => [
+ if (returnType != null) returnType!,
+ ' Function',
+ if (typeParameters.isNotEmpty) ...[
+ '<',
+ ...typeParameters.joinAsCode(', '),
+ '>',
+ ],
+ '(',
+ for (ParameterCode positional in positionalParameters) ...[
+ positional,
+ ', ',
+ ],
+ if (namedParameters.isNotEmpty) ...[
+ '{',
+ for (ParameterCode named in namedParameters) ...[
+ named,
+ ', ',
+ ],
+ '}',
+ ],
+ ')',
+ ];
+
+ FunctionTypeAnnotationCode({
+ this.namedParameters = const [],
+ this.positionalParameters = const [],
+ this.returnType,
+ this.typeParameters = const [],
+ });
+}
+
+/// A piece of code representing a valid named type parameter.
+class TypeParameterCode implements Code {
+ final TypeAnnotationCode? bound;
+ final String name;
+
+ @override
+ CodeKind get kind => CodeKind.typeParameter;
+
+ @override
+ List<Object> get parts => [
+ name,
+ if (bound != null) ...[
+ ' extends ',
+ bound!,
+ ]
+ ];
+
+ TypeParameterCode({this.bound, required this.name});
+}
+
+extension Join<T extends Object> on List<T> {
/// Joins all the items in [this] with [separator], and returns
/// a new list.
- List<Code> joinAsCode(String separator) => [
+ List<Object> joinAsCode(String separator) => [
for (int i = 0; i < length - 1; i++) ...[
this[i],
- new Code.fromString(separator),
+ separator,
],
last,
];
}
enum CodeKind {
- raw,
declaration,
- element,
expression,
functionBody,
- namedArgument,
+ functionTypeAnnotation,
+ namedTypeAnnotation,
+ nullableTypeAnnotation,
parameter,
- statement,
+ raw,
+ typeParameter,
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
index d78d9e4..f9296fc 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
@@ -24,10 +24,9 @@
/// trailing `?`)
bool get isNullable;
- /// A convenience method to get a [Code] object representation of this full
- /// type annotation, including support for generic type arguments as well as
- /// function types.
- Code get code;
+ /// A convenience method to get a [Code] object equivalent to this type
+ /// annotation.
+ TypeAnnotationCode get code;
}
/// The base class for function type declarations.
@@ -176,10 +175,6 @@
/// The type of this field.
TypeAnnotation get type;
-
- /// A [ExpressionCode] object representing the initializer for this field, if
- /// present.
- ExpressionCode? get initializer;
}
/// Field introspection information.
@@ -198,13 +193,19 @@
/// parameter or an optional parameter with the `required` keyword.
bool get isRequired;
- /// A [Code] object representing the default value for this parameter, if
- /// present. Can be used to copy default values to other parameters.
- Code? get defaultValue;
+ /// A convenience method to get a `code` object equivalent to this parameter.
+ ///
+ /// Note that the original default value will not be included, as it is not a
+ /// part of this API.
+ ParameterCode get code;
}
/// Type parameter introspection information.
abstract class TypeParameterDeclaration implements Declaration {
- /// The bounds for this type parameter, if it has any.
- TypeAnnotation? get bounds;
+ /// The bound for this type parameter, if it has any.
+ TypeAnnotation? get bound;
+
+ /// A convenience method to get a `code` object equivalent to this type
+ /// parameter.
+ TypeParameterCode get code;
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
index caba317..9f14be98 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
@@ -72,12 +72,8 @@
classIntrospector.superclassOf(clazz);
@override
- Future<StaticType> instantiateCode(ExpressionCode code) =>
- typeResolver.instantiateCode(code);
-
- @override
- Future<StaticType> instantiateType(TypeAnnotation typeAnnotation) =>
- typeResolver.instantiateType(typeAnnotation);
+ Future<StaticType> resolve(TypeAnnotationCode code) =>
+ typeResolver.resolve(code);
}
class DeclarationBuilderImpl extends DeclarationBuilderBase
@@ -323,31 +319,23 @@
'<',
for (TypeParameterDeclaration typeParam
in declaration.typeParameters) ...[
- typeParam.identifier,
- if (typeParam.bounds != null) ...['extends ', typeParam.bounds!.code],
+ typeParam.identifier.name,
+ if (typeParam.bound != null) ...[' extends ', typeParam.bound!.code],
if (typeParam != declaration.typeParameters.last) ', ',
],
'>',
],
'(',
for (ParameterDeclaration positionalRequired
- in declaration.positionalParameters.where((p) => p.isRequired)) ...[
- new ParameterCode.fromParts([
- positionalRequired.type.code,
- ' ',
- positionalRequired.identifier.name,
- ]),
- ', '
+ in declaration.positionalParameters.takeWhile((p) => p.isRequired)) ...[
+ positionalRequired.code,
+ ', ',
],
if (declaration.positionalParameters.any((p) => !p.isRequired)) ...[
'[',
for (ParameterDeclaration positionalOptional
in declaration.positionalParameters.where((p) => !p.isRequired)) ...[
- new ParameterCode.fromParts([
- positionalOptional.type.code,
- ' ',
- positionalOptional.identifier.name,
- ]),
+ positionalOptional.code,
', ',
],
']',
@@ -355,16 +343,7 @@
if (declaration.namedParameters.isNotEmpty) ...[
'{',
for (ParameterDeclaration named in declaration.namedParameters) ...[
- new ParameterCode.fromParts([
- if (named.isRequired) 'required ',
- named.type.code,
- ' ',
- named.identifier,
- if (named.defaultValue != null) ...[
- ' = ',
- named.defaultValue!,
- ],
- ]),
+ named.code,
', ',
],
'}',
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
index 9fbb7c1..baf884d 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
@@ -48,16 +48,13 @@
class NamedTypeAnnotationImpl extends TypeAnnotationImpl
implements NamedTypeAnnotation {
@override
- Code get code => new Code.fromParts([
- identifier,
- if (typeArguments.isNotEmpty) ...[
- '<',
- typeArguments.first.code,
- for (TypeAnnotation arg in typeArguments.skip(1)) ...[', ', arg.code],
- '>',
- ],
- if (isNullable) '?',
- ]);
+ TypeAnnotationCode get code {
+ NamedTypeAnnotationCode underlyingType =
+ new NamedTypeAnnotationCode(name: identifier, typeArguments: [
+ for (TypeAnnotation typeArg in typeArguments) typeArg.code,
+ ]);
+ return isNullable ? underlyingType.asNullable : underlyingType;
+ }
@override
final IdentifierImpl identifier;
@@ -95,39 +92,23 @@
class FunctionTypeAnnotationImpl extends TypeAnnotationImpl
implements FunctionTypeAnnotation {
@override
- Code get code => new Code.fromParts([
- returnType.code,
- 'Function',
- if (typeParameters.isNotEmpty) ...[
- '<',
- typeParameters.first.identifier.name,
- if (typeParameters.first.bounds != null) ...[
- ' extends ',
- typeParameters.first.bounds!.code,
- ],
- for (TypeParameterDeclaration arg in typeParameters.skip(1)) ...[
- ', ',
- arg.identifier.name,
- if (arg.bounds != null) ...[' extends ', arg.bounds!.code],
- ],
- '>',
- ],
- '(',
- for (ParameterDeclaration positional in positionalParameters) ...[
- positional.type.code,
- ' ${positional.identifier.name}',
- ],
- if (namedParameters.isNotEmpty) ...[
- '{',
- for (ParameterDeclaration named in namedParameters) ...[
- named.type.code,
- ' ${named.identifier.name}',
- ],
- '}',
- ],
- ')',
- if (isNullable) '?',
- ]);
+ TypeAnnotationCode get code {
+ FunctionTypeAnnotationCode underlyingType = new FunctionTypeAnnotationCode(
+ returnType: returnType.code,
+ typeParameters: [
+ for (TypeParameterDeclaration typeParam in typeParameters)
+ typeParam.code,
+ ],
+ positionalParameters: [
+ for (ParameterDeclaration positional in positionalParameters)
+ positional.code,
+ ],
+ namedParameters: [
+ for (ParameterDeclaration named in namedParameters) named.code,
+ ],
+ );
+ return isNullable ? underlyingType.asNullable : underlyingType;
+ }
@override
final List<ParameterDeclarationImpl> namedParameters;
@@ -203,9 +184,6 @@
class ParameterDeclarationImpl extends DeclarationImpl
implements ParameterDeclaration {
@override
- final Code? defaultValue;
-
- @override
final bool isNamed;
@override
@@ -220,7 +198,6 @@
ParameterDeclarationImpl({
required int id,
required IdentifierImpl identifier,
- required this.defaultValue,
required this.isNamed,
required this.isRequired,
required this.type,
@@ -234,21 +211,22 @@
return;
}
- if (defaultValue == null) {
- serializer.addNull();
- } else {
- defaultValue!.serialize(serializer);
- }
serializer.addBool(isNamed);
serializer.addBool(isRequired);
type.serialize(serializer);
}
+
+ @override
+ ParameterCode get code =>
+ new ParameterCode(name: identifier.name, type: type.code, keywords: [
+ if (isNamed && isRequired) 'required',
+ ]);
}
class TypeParameterDeclarationImpl extends DeclarationImpl
implements TypeParameterDeclaration {
@override
- final TypeAnnotationImpl? bounds;
+ final TypeAnnotationImpl? bound;
@override
RemoteInstanceKind get kind => RemoteInstanceKind.typeParameterDeclaration;
@@ -256,7 +234,7 @@
TypeParameterDeclarationImpl({
required int id,
required IdentifierImpl identifier,
- required this.bounds,
+ required this.bound,
}) : super(id: id, identifier: identifier);
@override
@@ -267,13 +245,17 @@
return;
}
- TypeAnnotationImpl? bounds = this.bounds;
- if (bounds == null) {
+ TypeAnnotationImpl? bound = this.bound;
+ if (bound == null) {
serializer.addNull();
} else {
- bounds.serialize(serializer);
+ bound.serialize(serializer);
}
}
+
+ @override
+ TypeParameterCode get code =>
+ new TypeParameterCode(name: identifier.name, bound: bound?.code);
}
class FunctionDeclarationImpl extends DeclarationImpl
@@ -462,9 +444,6 @@
class VariableDeclarationImpl extends DeclarationImpl
implements VariableDeclaration {
@override
- final ExpressionCode? initializer;
-
- @override
final bool isExternal;
@override
@@ -482,7 +461,6 @@
VariableDeclarationImpl({
required int id,
required IdentifierImpl identifier,
- required this.initializer,
required this.isExternal,
required this.isFinal,
required this.isLate,
@@ -497,7 +475,6 @@
return;
}
- initializer.serializeNullable(serializer);
serializer
..addBool(isExternal)
..addBool(isFinal)
@@ -516,7 +493,6 @@
required int id,
required IdentifierImpl identifier,
// Variable fields
- required ExpressionCode? initializer,
required bool isExternal,
required bool isFinal,
required bool isLate,
@@ -526,7 +502,6 @@
}) : super(
id: id,
identifier: identifier,
- initializer: initializer,
isExternal: isExternal,
isFinal: isFinal,
isLate: isLate,
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
index 7dd6004..f3a3bf7 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
@@ -343,26 +343,26 @@
}
}
-/// A request to reflect on a type annotation
-class InstantiateTypeRequest extends Request {
- final TypeAnnotationImpl typeAnnotation;
+/// A request to resolve on a type annotation code object
+class ResolveTypeRequest extends Request {
+ final TypeAnnotationCode typeAnnotationCode;
final RemoteInstanceImpl typeResolver;
- InstantiateTypeRequest(this.typeAnnotation, this.typeResolver,
+ ResolveTypeRequest(this.typeAnnotationCode, this.typeResolver,
{required int serializationZoneId})
: super(serializationZoneId: serializationZoneId);
/// When deserializing we have already consumed the message type, so we don't
/// consume it again.
- InstantiateTypeRequest.deserialize(
+ ResolveTypeRequest.deserialize(
Deserializer deserializer, int serializationZoneId)
- : typeAnnotation = RemoteInstance.deserialize(deserializer),
+ : typeAnnotationCode = (deserializer..moveNext()).expectCode(),
typeResolver = RemoteInstance.deserialize(deserializer),
super.deserialize(deserializer, serializationZoneId);
void serialize(Serializer serializer) {
- serializer.addNum(MessageType.instantiateTypeRequest.index);
- typeAnnotation.serialize(serializer);
+ serializer.addNum(MessageType.resolveTypeRequest.index);
+ typeAnnotationCode.serialize(serializer);
typeResolver.serialize(serializer);
super.serialize(serializer);
}
@@ -491,8 +491,8 @@
{required this.remoteInstance, required this.serializationZoneId});
@override
- Future<StaticType> instantiateType(TypeAnnotationImpl typeAnnotation) async {
- InstantiateTypeRequest request = new InstantiateTypeRequest(
+ Future<StaticType> resolve(TypeAnnotationCode typeAnnotation) async {
+ ResolveTypeRequest request = new ResolveTypeRequest(
typeAnnotation, remoteInstance,
serializationZoneId: serializationZoneId);
RemoteInstanceImpl remoteType =
@@ -512,12 +512,6 @@
'${remoteType.kind}');
}
}
-
- @override
- Future<StaticType> instantiateCode(ExpressionCode code) {
- // TODO: implement instantiateCode
- throw new UnimplementedError();
- }
}
class ClientStaticTypeImpl implements StaticType {
@@ -705,7 +699,7 @@
executeDefinitionsPhaseRequest,
executeTypesPhaseRequest,
instantiateMacroRequest,
- instantiateTypeRequest,
+ resolveTypeRequest,
isExactlyTypeRequest,
isSubtypeOfRequest,
loadMacroRequest,
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
index d11ec37..191509f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
@@ -97,7 +97,6 @@
new ParameterDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
- defaultValue: (this..moveNext()).checkNull() ? null : expectCode(),
isNamed: (this..moveNext()).expectBool(),
isRequired: (this..moveNext()).expectBool(),
type: RemoteInstance.deserialize(this),
@@ -107,7 +106,7 @@
new TypeParameterDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
- bounds: (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
+ bound: (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
);
FunctionDeclaration _expectFunctionDeclaration(int id) =>
@@ -162,7 +161,6 @@
new VariableDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
- initializer: (this..moveNext()).expectNullableCode(),
isExternal: (this..moveNext()).expectBool(),
isFinal: (this..moveNext()).expectBool(),
isLate: (this..moveNext()).expectBool(),
@@ -172,7 +170,6 @@
FieldDeclaration _expectFieldDeclaration(int id) => new FieldDeclarationImpl(
id: id,
identifier: expectRemoteInstance(),
- initializer: (this..moveNext()).expectNullableCode(),
isExternal: (this..moveNext()).expectBool(),
isFinal: (this..moveNext()).expectBool(),
isLate: (this..moveNext()).expectBool(),
@@ -200,44 +197,83 @@
aliasedType: RemoteInstance.deserialize(this),
);
- T expectCode<T extends Code>() {
- CodeKind kind = CodeKind.values[expectNum()];
+ List<String> _readStringList() => [
+ for (bool hasNext = (this
+ ..moveNext()
+ ..expectList())
+ .moveNext();
+ hasNext;
+ hasNext = moveNext())
+ expectString(),
+ ];
+
+ List<T> _readCodeList<T extends Code>() => [
+ for (bool hasNext = (this
+ ..moveNext()
+ ..expectList())
+ .moveNext();
+ hasNext;
+ hasNext = moveNext())
+ expectCode(),
+ ];
+
+ List<Object> _readParts() {
moveNext();
expectList();
List<Object> parts = [];
while (moveNext()) {
- CodePartKind partKind = CodePartKind.values[expectNum()];
+ _CodePartKind partKind = _CodePartKind.values[expectNum()];
moveNext();
switch (partKind) {
- case CodePartKind.code:
+ case _CodePartKind.code:
parts.add(expectCode());
break;
- case CodePartKind.string:
+ case _CodePartKind.string:
parts.add(expectString());
break;
- case CodePartKind.identifier:
+ case _CodePartKind.identifier:
parts.add(expectRemoteInstance());
break;
}
}
+ return parts;
+ }
+
+ T expectCode<T extends Code>() {
+ CodeKind kind = CodeKind.values[expectNum()];
switch (kind) {
case CodeKind.raw:
- return new Code.fromParts(parts) as T;
+ return new Code.fromParts(_readParts()) as T;
case CodeKind.declaration:
- return new DeclarationCode.fromParts(parts) as T;
- case CodeKind.element:
- return new ElementCode.fromParts(parts) as T;
+ return new DeclarationCode.fromParts(_readParts()) as T;
case CodeKind.expression:
- return new ExpressionCode.fromParts(parts) as T;
+ return new ExpressionCode.fromParts(_readParts()) as T;
case CodeKind.functionBody:
- return new FunctionBodyCode.fromParts(parts) as T;
- case CodeKind.namedArgument:
- return new NamedArgumentCode.fromParts(parts) as T;
+ return new FunctionBodyCode.fromParts(_readParts()) as T;
+ case CodeKind.functionTypeAnnotation:
+ return new FunctionTypeAnnotationCode(
+ namedParameters: _readCodeList(),
+ positionalParameters: _readCodeList(),
+ returnType: (this..moveNext()).expectNullableCode(),
+ typeParameters: _readCodeList()) as T;
+ case CodeKind.namedTypeAnnotation:
+ return new NamedTypeAnnotationCode(
+ name: RemoteInstance.deserialize(this),
+ typeArguments: _readCodeList()) as T;
+ case CodeKind.nullableTypeAnnotation:
+ return new NullableTypeAnnotationCode((this..moveNext()).expectCode())
+ as T;
case CodeKind.parameter:
- return new ParameterCode.fromParts(parts) as T;
- case CodeKind.statement:
- return new StatementCode.fromParts(parts) as T;
+ return new ParameterCode(
+ defaultValue: (this..moveNext()).expectNullableCode(),
+ keywords: _readStringList(),
+ name: (this..moveNext()).expectString(),
+ type: (this..moveNext()).expectNullableCode()) as T;
+ case CodeKind.typeParameter:
+ return new TypeParameterCode(
+ bound: (this..moveNext()).expectNullableCode(),
+ name: (this..moveNext()).expectString()) as T;
}
}
@@ -273,29 +309,82 @@
extension SerializeCode on Code {
void serialize(Serializer serializer) {
- serializer
- ..addNum(kind.index)
- ..startList();
- for (Object part in parts) {
- if (part is String) {
+ serializer.addNum(kind.index);
+ switch (kind) {
+ case CodeKind.namedTypeAnnotation:
+ NamedTypeAnnotationCode self = this as NamedTypeAnnotationCode;
+ (self.name as IdentifierImpl).serialize(serializer);
+ serializer.startList();
+ for (TypeAnnotationCode typeArg in self.typeArguments) {
+ typeArg.serialize(serializer);
+ }
+ serializer.endList();
+ return;
+ case CodeKind.functionTypeAnnotation:
+ FunctionTypeAnnotationCode self = this as FunctionTypeAnnotationCode;
+ serializer.startList();
+ for (ParameterCode named in self.namedParameters) {
+ named.serialize(serializer);
+ }
serializer
- ..addNum(CodePartKind.string.index)
- ..addString(part);
- } else if (part is Code) {
- serializer.addNum(CodePartKind.code.index);
- part.serialize(serializer);
- } else if (part is IdentifierImpl) {
- serializer.addNum(CodePartKind.identifier.index);
- part.serialize(serializer);
- } else {
- throw new StateError('Unrecognized code part $part');
- }
+ ..endList()
+ ..startList();
+ for (ParameterCode positional in self.positionalParameters) {
+ positional.serialize(serializer);
+ }
+ serializer..endList();
+ self.returnType.serializeNullable(serializer);
+ serializer.startList();
+ for (TypeParameterCode typeParam in self.typeParameters) {
+ typeParam.serialize(serializer);
+ }
+ serializer.endList();
+ return;
+ case CodeKind.nullableTypeAnnotation:
+ NullableTypeAnnotationCode self = this as NullableTypeAnnotationCode;
+ self.underlyingType.serialize(serializer);
+ return;
+ case CodeKind.parameter:
+ ParameterCode self = this as ParameterCode;
+ self.defaultValue.serializeNullable(serializer);
+ serializer.startList();
+ for (String keyword in self.keywords) {
+ serializer.addString(keyword);
+ }
+ serializer
+ ..endList()
+ ..addString(self.name);
+ self.type.serializeNullable(serializer);
+ return;
+ case CodeKind.typeParameter:
+ TypeParameterCode self = this as TypeParameterCode;
+ self.bound.serializeNullable(serializer);
+ serializer.addString(self.name);
+ return;
+ default:
+ serializer.startList();
+ for (Object part in parts) {
+ if (part is String) {
+ serializer
+ ..addNum(_CodePartKind.string.index)
+ ..addString(part);
+ } else if (part is Code) {
+ serializer.addNum(_CodePartKind.code.index);
+ part.serialize(serializer);
+ } else if (part is IdentifierImpl) {
+ serializer.addNum(_CodePartKind.identifier.index);
+ part.serialize(serializer);
+ } else {
+ throw new StateError('Unrecognized code part $part');
+ }
+ }
+ serializer.endList();
+ return;
}
- serializer.endList();
}
}
-enum CodePartKind {
+enum _CodePartKind {
string,
code,
identifier,
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
index 198d388..7713aa3 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
@@ -151,12 +151,12 @@
}
completer.complete(response);
break;
- case MessageType.instantiateTypeRequest:
- InstantiateTypeRequest request =
- new InstantiateTypeRequest.deserialize(deserializer, zoneId);
+ case MessageType.resolveTypeRequest:
+ ResolveTypeRequest request =
+ new ResolveTypeRequest.deserialize(deserializer, zoneId);
StaticType instance =
await (request.typeResolver.instance as TypeResolver)
- .instantiateType(request.typeAnnotation);
+ .resolve(request.typeAnnotationCode);
SerializableResponse response = new SerializableResponse(
response: new RemoteInstanceImpl(
id: RemoteInstance.uniqueId,
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
index aabcf97..879ae11 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
@@ -124,7 +124,6 @@
final fooNamedParam = ParameterDeclarationImpl(
id: RemoteInstance.uniqueId,
- defaultValue: null,
isNamed: true,
isRequired: true,
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'foo'),
@@ -132,7 +131,6 @@
final barPositionalParam = ParameterDeclarationImpl(
id: RemoteInstance.uniqueId,
- defaultValue: Code.fromString('const Bar()'),
isNamed: false,
isRequired: false,
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
@@ -141,7 +139,7 @@
final zapTypeParam = TypeParameterDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Zap'),
- bounds: barType);
+ bound: barType);
// Transitively tests `TypeParameterDeclaration` and
// `ParameterDeclaration`.
@@ -218,7 +216,6 @@
isExternal: true,
isFinal: false,
isLate: true,
- initializer: ExpressionCode.fromString('Bar()'),
type: barType,
);
expectSerializationEquality(bar);
@@ -231,7 +228,6 @@
isExternal: false,
isFinal: true,
isLate: false,
- initializer: null,
type: barType,
definingClass: fooType.identifier,
);
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
index 30fac31..a2223c9 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
@@ -77,7 +77,7 @@
typeParameters: [],
),
TestTypeResolver({
- returnType:
+ returnType.identifier:
TestNamedStaticType(returnType.identifier, 'dart:core', [])
}),
FakeClassIntrospector(),
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
index 7972041..f23aa43 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
@@ -27,7 +27,7 @@
}
// Test the type resolver and static type interfaces
- var staticReturnType = await builder.instantiateType(method.returnType);
+ var staticReturnType = await builder.resolve(method.returnType.code);
if (!(await staticReturnType.isExactly(staticReturnType))) {
throw StateError('The return type should be exactly equal to itself!');
}
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
index cdd1725..5710e81 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
@@ -350,7 +350,7 @@
augment super = value;
}'''),
equalsIgnoringWhitespace('''
- augment final String _myVariable = '';
+ augment final String _myVariable = 'new initial value' + augment super;
'''),
]));
});
@@ -415,6 +415,7 @@
augment set myField(String value) {
augment super = value;
}
+ augment String myField = \'new initial value\' + augment super;
}''');
final methodDefinitionMatchers = [
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
index 79f9b2e..b5a2d2d 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
@@ -204,7 +204,7 @@
var constructors = (await builder.constructorsOf(parentClass));
// Test the type resolver and static type interfaces
- var staticReturnType = await builder.instantiateType(method.returnType);
+ var staticReturnType = await builder.resolve(method.returnType.code);
if (!(await staticReturnType.isExactly(staticReturnType))) {
throw StateError('The return type should be exactly equal to itself!');
}
@@ -213,8 +213,7 @@
}
// TODO: Use `builder.instantiateCode` instead once implemented.
- var classType =
- await builder.instantiateType(constructors.first.returnType);
+ var classType = await builder.resolve(constructors.first.returnType.code);
if (await staticReturnType.isExactly(classType)) {
throw StateError(
'The return type should not be exactly equal to the class type');
@@ -270,7 +269,8 @@
variable.type.code,
' value) { augment super = value; }'
]),
- initializer: variable.initializer,
+ initializer:
+ ExpressionCode.fromString("'new initial value' + augment super"),
);
}
@@ -282,9 +282,9 @@
return [
if (!isFirst) ', ',
typeParam.identifier.name,
- if (typeParam.bounds != null) ...[
+ if (typeParam.bound != null) ...[
' extends ',
- typeParam.bounds!.code,
+ typeParam.bound!.code,
]
];
}
@@ -374,19 +374,17 @@
"print('positionalParam: ",
param.type.code,
' ${param.identifier.name}',
- if (param.defaultValue != null) ...[' = ', param.defaultValue!],
"');\n",
],
for (var param in function.namedParameters) ...[
"print('namedParam: ",
param.type.code,
' ${param.identifier.name}',
- if (param.defaultValue != null) ...[' = ', param.defaultValue!],
"');\n",
],
for (var param in function.typeParameters) ...[
"print('typeParam: ${param.identifier.name} ",
- if (param.bounds != null) param.bounds!.code,
+ if (param.bound != null) param.bound!.code,
"');\n",
],
'return augment super',
diff --git a/pkg/_fe_analyzer_shared/test/macros/util.dart b/pkg/_fe_analyzer_shared/test/macros/util.dart
index d9c1f51..34625b2 100644
--- a/pkg/_fe_analyzer_shared/test/macros/util.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/util.dart
@@ -76,20 +76,14 @@
}
class TestTypeResolver implements TypeResolver {
- final Map<TypeAnnotation, StaticType> staticTypes;
+ final Map<Identifier, StaticType> staticTypes;
TestTypeResolver(this.staticTypes);
@override
- Future<StaticType> instantiateType(
- covariant TypeAnnotation typeAnnotation) async {
- return staticTypes[typeAnnotation]!;
- }
-
- @override
- Future<StaticType> instantiateCode(ExpressionCode code) {
- // TODO: implement instantiateCode
- throw UnimplementedError();
+ Future<StaticType> resolve(covariant TypeAnnotationCode type) async {
+ assert(type.parts.length == 1);
+ return staticTypes[type.parts.first]!;
}
}
@@ -262,7 +256,6 @@
id: RemoteInstance.uniqueId,
identifier:
IdentifierImpl(id: RemoteInstance.uniqueId, name: '_myVariable'),
- initializer: ExpressionCode.fromString("''"),
isExternal: false,
isFinal: true,
isLate: false,
@@ -295,7 +288,6 @@
id: RemoteInstance.uniqueId,
identifier:
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'value'),
- defaultValue: null,
isNamed: false,
isRequired: true,
type: stringType)
@@ -353,7 +345,6 @@
static final myField = FieldDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myField'),
- initializer: null,
isExternal: false,
isFinal: false,
isLate: false,
@@ -404,8 +395,9 @@
myClassType.identifier, 'package:my_package/my_package.dart', []);
static final testTypeResolver = TestTypeResolver({
- stringType: TestNamedStaticType(stringType.identifier, 'dart:core', []),
- myClassType: myClassStaticType,
+ stringType.identifier:
+ TestNamedStaticType(stringType.identifier, 'dart:core', []),
+ myClass.identifier: myClassStaticType,
});
static final testClassIntrospector = TestClassIntrospector(
constructors: {
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index ffba325..5e3a9c5 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -36,7 +36,6 @@
aliasedType: aliasedType,
parameters: elementParameters,
returnType: elementReturnType,
- libraryUri: element.library?.source.uri.toString(),
);
}
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 4f6aaaa3..25a8bf9 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -131,7 +131,7 @@
});
var result = CiderCompletionResult._(
- suggestions: suggestions,
+ suggestions: suggestions.map((e) => e.build()).toList(),
performance: CiderCompletionPerformance._(
operations: _performanceRoot.children.first,
),
@@ -157,25 +157,25 @@
///
/// TODO(scheglov) Implement show / hide combinators.
/// TODO(scheglov) Implement prefixes.
- List<CompletionSuggestion> _importedLibrariesSuggestions({
+ List<CompletionSuggestionBuilder> _importedLibrariesSuggestions({
required LibraryElement target,
required OperationPerformanceImpl performance,
}) {
- var suggestions = <CompletionSuggestion>[];
+ var suggestionBuilders = <CompletionSuggestionBuilder>[];
for (var importedLibrary in target.importedLibraries) {
var importedSuggestions = _importedLibrarySuggestions(
element: importedLibrary,
performance: performance,
);
- suggestions.addAll(importedSuggestions);
+ suggestionBuilders.addAll(importedSuggestions);
}
- performance.getDataInt('count').add(suggestions.length);
- return suggestions;
+ performance.getDataInt('count').add(suggestionBuilders.length);
+ return suggestionBuilders;
}
/// Return cached, or compute unprefixed suggestions for all elements
/// exported from the library.
- List<CompletionSuggestion> _importedLibrarySuggestions({
+ List<CompletionSuggestionBuilder> _importedLibrarySuggestions({
required LibraryElement element,
required OperationPerformanceImpl performance,
}) {
@@ -198,13 +198,15 @@
);
_cache._importedLibraries[path] = cacheEntry;
}
- return cacheEntry.suggestions;
+ return cacheEntry.suggestionBuilders;
}
/// Compute all unprefixed suggestions for all elements exported from
/// the library.
- List<CompletionSuggestion> _librarySuggestions(LibraryElement element) {
+ List<CompletionSuggestionBuilder> _librarySuggestions(
+ LibraryElement element) {
var suggestionBuilder = SuggestionBuilder(_dartCompletionRequest);
+ suggestionBuilder.libraryUriStr = element.source.uri.toString();
var visitor = LibraryElementSuggestionBuilder(
_dartCompletionRequest, suggestionBuilder);
var exportMap = element.exportNamespace.definedNames;
@@ -250,7 +252,7 @@
class _CiderImportedLibrarySuggestions {
final String signature;
- final List<CompletionSuggestion> suggestions;
+ final List<CompletionSuggestionBuilder> suggestionBuilders;
- _CiderImportedLibrarySuggestions(this.signature, this.suggestions);
+ _CiderImportedLibrarySuggestions(this.signature, this.suggestionBuilders);
}
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 45ccc9b..9f3043e 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -68,7 +68,7 @@
/// automatically called when a client listens to the stream returned by
/// [results]. Subclasses should override this method, append at least one
/// result to the [controller], and close the controller stream once complete.
- Future<List<CompletionSuggestion>> computeSuggestions({
+ Future<List<CompletionSuggestionBuilder>> computeSuggestions({
required CompletionBudget budget,
required OperationPerformanceImpl performance,
required DartCompletionRequest request,
@@ -87,7 +87,7 @@
//
// Compute completions generated by server.
//
- var suggestions = <CompletionSuggestion>[];
+ var suggestions = <CompletionSuggestionBuilder>[];
await performance.runAsync('computeSuggestions', (performance) async {
var manager = DartCompletionManager(
budget: budget,
@@ -357,9 +357,9 @@
setNewRequest(completionRequest);
var notImportedSuggestions = NotImportedSuggestions();
- var suggestions = <CompletionSuggestion>[];
+ var suggestionBuilders = <CompletionSuggestionBuilder>[];
try {
- suggestions = await computeSuggestions(
+ suggestionBuilders = await computeSuggestions(
budget: budget,
performance: performance,
request: completionRequest,
@@ -377,36 +377,29 @@
}
performance.run('filter', (performance) {
- performance.getDataInt('count').add(suggestions.length);
- suggestions = fuzzyFilterSort(
+ performance.getDataInt('count').add(suggestionBuilders.length);
+ suggestionBuilders = fuzzyFilterSort(
pattern: completionRequest.targetPrefix,
- suggestions: suggestions,
+ suggestions: suggestionBuilders,
);
- performance.getDataInt('matchCount').add(suggestions.length);
+ performance.getDataInt('matchCount').add(suggestionBuilders.length);
});
- var lengthRestricted = suggestions.take(params.maxResults).toList();
+ var lengthRestricted =
+ suggestionBuilders.take(params.maxResults).toList();
completionPerformance.suggestionCount = lengthRestricted.length;
- // Update `isNotImported` for not yet imported.
- for (var i = 0; i < lengthRestricted.length; i++) {
- var suggestion = lengthRestricted[i];
- if (notImportedSuggestions.set.contains(suggestion)) {
- lengthRestricted[i] = suggestion.copyWith(
- isNotImported: CopyWithValue(true),
- );
- }
- }
+ var suggestions = lengthRestricted.map((e) => e.build()).toList();
var isIncomplete = notImportedSuggestions.isIncomplete ||
- lengthRestricted.length < suggestions.length;
+ lengthRestricted.length < suggestionBuilders.length;
performance.run('sendResponse', (_) {
server.sendResponse(
CompletionGetSuggestions2Result(
completionRequest.replacementOffset,
completionRequest.replacementLength,
- lengthRestricted,
+ suggestions,
isIncomplete,
).toResponse(request.id),
);
@@ -569,9 +562,9 @@
// Compute suggestions in the background
try {
- var suggestions = <CompletionSuggestion>[];
+ var suggestionBuilders = <CompletionSuggestionBuilder>[];
try {
- suggestions = await computeSuggestions(
+ suggestionBuilders = await computeSuggestions(
budget: budget,
performance: performance,
request: completionRequest,
@@ -603,7 +596,7 @@
completionId,
completionRequest.replacementOffset,
completionRequest.replacementLength,
- suggestions,
+ suggestionBuilders.map((e) => e.build()).toList(),
libraryFile,
includedSuggestionSets,
includedElementKinds?.toList(),
@@ -611,7 +604,7 @@
);
});
- completionPerformance.suggestionCount = suggestions.length;
+ completionPerformance.suggestionCount = suggestionBuilders.length;
} finally {
ifMatchesRequestClear(completionRequest);
}
@@ -694,7 +687,7 @@
Future<void> _addPluginSuggestions(
CompletionBudget budget,
_RequestToPlugins requestToPlugins,
- List<CompletionSuggestion> suggestions,
+ List<CompletionSuggestionBuilder> suggestionBuilders,
) async {
var responses = await waitForResponses(
requestToPlugins.futures,
@@ -712,7 +705,11 @@
' replacement offset/length: ${result.toJson()}');
continue;
}
- suggestions.addAll(result.results);
+ suggestionBuilders.addAll(
+ result.results.map(
+ (suggestion) => ValueCompletionSuggestionBuilder(suggestion),
+ ),
+ );
}
}
}
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index e0eedc4..4fc64eb 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -74,12 +74,13 @@
offset: targetOffset,
);
- var suggestions = await DartCompletionManager(
+ var serverSuggestions = await DartCompletionManager(
budget: CompletionBudget(CompletionBudget.defaultDuration),
).computeSuggestions(
dartRequest,
OperationPerformanceImpl('<root>'),
);
+ var suggestions = serverSuggestions.map((e) => e.build()).toList();
// Remove completions with synthetic import prefixes.
suggestions.removeWhere((s) => s.completion.startsWith('__prefix'));
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 736ab90..6338b96 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -256,11 +256,15 @@
includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
);
- final serverSuggestions = await contributor.computeSuggestions(
+ final serverSuggestions2 = await contributor.computeSuggestions(
completionRequest,
performance,
);
+ final serverSuggestions = serverSuggestions2.map((serverSuggestion) {
+ return serverSuggestion.build();
+ }).toList();
+
final insertLength = _computeInsertLength(
offset,
completionRequest.replacementOffset,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index b2ef7d6d..53b553c 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -117,7 +117,7 @@
includedElementNames == null &&
includedSuggestionRelevanceTags == null));
- Future<List<CompletionSuggestion>> computeSuggestions(
+ Future<List<CompletionSuggestionBuilder>> computeSuggestions(
DartCompletionRequest request,
OperationPerformanceImpl performance, {
bool enableOverrideContributor = true,
@@ -126,12 +126,12 @@
request.checkAborted();
var pathContext = request.resourceProvider.pathContext;
if (!file_paths.isDart(pathContext, request.path)) {
- return const <CompletionSuggestion>[];
+ return const <CompletionSuggestionBuilder>[];
}
// Don't suggest in comments.
if (request.target.isCommentText) {
- return const <CompletionSuggestion>[];
+ return const <CompletionSuggestionBuilder>[];
}
request.checkAborted();
@@ -503,8 +503,6 @@
/// Information provided by [NotImportedContributor] in addition to suggestions.
class NotImportedSuggestions {
- final Set<protocol.CompletionSuggestion> set = Set.identity();
-
/// This flag is set to `true` if the contributor decided to stop before it
/// processed all available libraries, e.g. we ran out of budget.
bool isIncomplete = false;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart b/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
index 4408a7a..59a5f61 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
@@ -3,17 +3,18 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/services/completion/filtering/fuzzy_matcher.dart';
/// Filters and scores [suggestions] according to how well they match the
/// [pattern]. Sorts [suggestions] by the score, relevance, and name.
-List<CompletionSuggestion> fuzzyFilterSort({
+List<CompletionSuggestionBuilder> fuzzyFilterSort({
required String pattern,
- required List<CompletionSuggestion> suggestions,
+ required List<CompletionSuggestionBuilder> suggestions,
}) {
var matcher = FuzzyMatcher(pattern, matchStyle: MatchStyle.SYMBOL);
- double score(CompletionSuggestion suggestion) {
+ double score(CompletionSuggestionBuilder suggestion) {
var suggestionTextToMatch = suggestion.completion;
if (suggestion.kind == CompletionSuggestionKind.NAMED_ARGUMENT) {
@@ -53,7 +54,7 @@
/// [CompletionSuggestion] scored using [FuzzyMatcher].
class _FuzzyScoredSuggestion {
- final CompletionSuggestion suggestion;
+ final CompletionSuggestionBuilder suggestion;
final double score;
_FuzzyScoredSuggestion(this.suggestion, this.score);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
index 3277593..5ef87a7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
@@ -7,6 +7,7 @@
import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart'
show SuggestionBuilder;
+import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
/// A contributor for calculating suggestions for imported top level members.
@@ -27,8 +28,11 @@
for (var importElement in imports) {
var libraryElement = importElement.importedLibrary;
if (libraryElement != null) {
- _buildSuggestions(importElement.namespace,
- prefix: importElement.prefix?.name);
+ _buildSuggestions(
+ libraryElement: libraryElement,
+ namespace: importElement.namespace,
+ prefix: importElement.prefix?.name,
+ );
if (libraryElement.isDartCore &&
request.opType.includeTypeNameSuggestions) {
builder.suggestName('Never');
@@ -37,10 +41,16 @@
}
}
- void _buildSuggestions(Namespace namespace, {String? prefix}) {
+ void _buildSuggestions({
+ required LibraryElement libraryElement,
+ required Namespace namespace,
+ String? prefix,
+ }) {
+ builder.libraryUriStr = libraryElement.source.uri.toString();
var visitor = LibraryElementSuggestionBuilder(request, builder, prefix);
for (var elem in namespace.definedNames.values) {
elem.accept(visitor);
}
+ builder.libraryUriStr = null;
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
index d9675cb..b78b89e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
@@ -41,6 +41,7 @@
if (importElem.prefix?.name == elem.name) {
var library = importElem.importedLibrary;
if (library != null) {
+ builder.libraryUriStr = library.source.uri.toString();
for (var element in importElem.namespace.definedNames.values) {
if (typesOnly && isConstructor) {
// Suggest constructors from the imported libraries.
@@ -72,6 +73,7 @@
if (!typesOnly && importElem.isDeferred) {
builder.suggestLoadLibraryFunction(library.loadLibraryFunction);
}
+ builder.libraryUriStr = null;
}
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
index 8bbff4f..52e893e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
@@ -81,11 +81,9 @@
var exportNamespace = element.exportNamespace;
var exportElements = exportNamespace.definedNames.values.toList();
+ builder.libraryUriStr = file.uriStr;
builder.isNotImportedLibrary = true;
builder.laterReplacesEarlier = false;
- builder.suggestionAdded = (suggestion) {
- additionalData.set.add(suggestion);
- };
if (request.includeIdentifiers) {
_buildSuggestions(exportElements);
@@ -95,9 +93,9 @@
_extensions(exportElements),
);
+ builder.libraryUriStr = null;
builder.isNotImportedLibrary = false;
builder.laterReplacesEarlier = true;
- builder.suggestionAdded = null;
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 829a3e5..c1661dc 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -21,18 +21,122 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
-/// Wrapper around a potentially nullable value.
-///
-/// When the wrapper instance is provided for a property, the property
-/// value is replaced, even if the value to set is `null` itself.
-class CopyWithValue<T> {
- final T value;
+/// A container with enough information to do filtering, and if necessary
+/// build the [CompletionSuggestion] instance.
+abstract class CompletionSuggestionBuilder {
+ /// See [CompletionSuggestion.completion].
+ String get completion;
- CopyWithValue(this.value);
+ /// The key used to de-duplicate suggestions.
+ String get key => completion;
+
+ /// See [CompletionSuggestion.kind].
+ CompletionSuggestionKind get kind;
+
+ /// See [CompletionSuggestion.relevance].
+ int get relevance;
+
+ CompletionSuggestion build();
+}
+
+/// The implementation of [CompletionSuggestionBuilder] that is based on
+/// [ElementCompletionData] and location specific information.
+class CompletionSuggestionBuilderImpl implements CompletionSuggestionBuilder {
+ final ElementCompletionData element;
+
+ @override
+ final CompletionSuggestionKind kind;
+
+ @override
+ final int relevance;
+
+ final String? completionOverride;
+ final String? libraryUriStr;
+ final bool isNotImported;
+
+ CompletionSuggestionBuilderImpl({
+ required this.element,
+ required this.kind,
+ required this.completionOverride,
+ required this.relevance,
+ required this.libraryUriStr,
+ required this.isNotImported,
+ });
+
+ @override
+ String get completion => completionOverride ?? element.completion;
+
+ /// TODO(scheglov) implement better key for not-yet-imported
+ @override
+ String get key {
+ var key = completion;
+ if (element.element.kind == protocol.ElementKind.CONSTRUCTOR) {
+ key = '$key()';
+ }
+ return key;
+ }
+
+ @override
+ CompletionSuggestion build() {
+ return CompletionSuggestion(
+ kind,
+ relevance,
+ completion,
+ completion.length /*selectionOffset*/,
+ 0 /*selectionLength*/,
+ element.isDeprecated,
+ false /*isPotential*/,
+ element: element.element,
+ docSummary: element.documentation?.summary,
+ docComplete: element.documentation?.full,
+ declaringType: element.declaringType,
+ returnType: element.returnType,
+ requiredParameterCount: element.requiredParameterCount,
+ hasNamedParameters: element.hasNamedParameters,
+ parameterNames: element.parameterNames,
+ parameterTypes: element.parameterTypes,
+ defaultArgumentListString: element.defaultArgumentList?.text,
+ defaultArgumentListTextRanges: element.defaultArgumentList?.ranges,
+ libraryUri: libraryUriStr,
+ isNotImported: isNotImported ? true : null,
+ );
+ }
+}
+
+/// Information about an [Element] that does not depend on the location where
+/// this element is suggested. For some often used elements, such as classes,
+/// it might be cached, so created only once.
+class ElementCompletionData {
+ final String completion;
+ final bool isDeprecated;
+ final String? declaringType;
+ final String? returnType;
+ final List<String>? parameterNames;
+ final List<String>? parameterTypes;
+ final int? requiredParameterCount;
+ final bool? hasNamedParameters;
+ CompletionDefaultArgumentList? defaultArgumentList;
+ final _ElementDocumentation? documentation;
+ final protocol.Element element;
+
+ ElementCompletionData({
+ required this.completion,
+ required this.isDeprecated,
+ required this.declaringType,
+ required this.returnType,
+ required this.parameterNames,
+ required this.parameterTypes,
+ required this.requiredParameterCount,
+ required this.hasNamedParameters,
+ required this.defaultArgumentList,
+ required this.documentation,
+ required this.element,
+ });
}
/// This class provides suggestions based upon the visible instance members in
@@ -151,22 +255,6 @@
/// An object used to build a list of suggestions in response to a single
/// completion request.
class SuggestionBuilder {
- /// The cache of suggestions for [Element]s. We use it to avoid computing
- /// the same documentation, parameters, return type, etc for elements that
- /// are exactly the same (the same instances) as they were the last time.
- ///
- /// This cache works because:
- /// 1. Flutter applications usually reference many libraries, which they
- /// consume, but don't change. So, all their elements stay unchanged.
- /// 2. The analyzer keeps the same library instances loaded as the user
- /// types in the application, so the instances of all elements stay the
- /// same, and the cache works.
- /// 3. The analyzer does not patch elements (at least not after the linking
- /// process is done, and the elements are exposed to any client code). So,
- /// any type information, or documentation, stays the same. If this changes,
- /// we would need a signal, e.g. some modification counter on the element.
- static final _elementSuggestionCache = Expando<_CompletionSuggestionEntry>();
-
/// The completion request for which suggestions are being built.
final DartCompletionRequest request;
@@ -174,12 +262,13 @@
/// suggestions, or `null` if no notification should occur.
final SuggestionListener? listener;
- /// The function to be invoked when a new suggestion is added.
- void Function(protocol.CompletionSuggestion)? suggestionAdded;
-
/// A map from a completion identifier to a completion suggestion.
- final Map<String, CompletionSuggestion> _suggestionMap =
- <String, CompletionSuggestion>{};
+ final Map<String, CompletionSuggestionBuilder> _suggestionMap = {};
+
+ /// The URI of the library from which suggestions are being added.
+ /// This URI is not necessary the same as the URI that declares an element,
+ /// because of exports.
+ String? libraryUriStr;
/// This flag is set to `true` while adding suggestions for top-level
/// elements from not-yet-imported libraries.
@@ -211,7 +300,8 @@
/// Return an iterable that can be used to access the completion suggestions
/// that have been built.
- Iterable<CompletionSuggestion> get suggestions => _suggestionMap.values;
+ Iterable<CompletionSuggestionBuilder> get suggestions =>
+ _suggestionMap.values;
/// Return the name of the member containing the completion location, or
/// `null` if the completion location isn't within a member or if the target
@@ -279,11 +369,12 @@
superMatches: superMatches,
inheritanceDistance: inheritanceDistance,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
accessor,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -303,12 +394,13 @@
elementKind: elementKind,
isConstant: isConstant,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
parameter,
elementKind: protocol.ElementKind.PARAMETER,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -318,12 +410,13 @@
void suggestClass(ClassElement classElement, {String? prefix}) {
var relevance = _computeTopLevelRelevance(classElement,
elementType: _instantiateClassElement(classElement));
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
classElement,
kind: CompletionSuggestionKind.IDENTIFIER,
prefix: prefix,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -368,16 +461,20 @@
);
}
- _add(createSuggestion(
- completion: blockBuffer.toString(),
- displayText: '$parametersString {}',
- selectionOffset: blockSelectionOffset,
- ));
- _add(createSuggestion(
- completion: expressionBuffer.toString(),
- displayText: '$parametersString =>',
- selectionOffset: expressionSelectionOffset,
- ));
+ _addSuggestion(
+ createSuggestion(
+ completion: blockBuffer.toString(),
+ displayText: '$parametersString {}',
+ selectionOffset: blockSelectionOffset,
+ ),
+ );
+ _addSuggestion(
+ createSuggestion(
+ completion: expressionBuffer.toString(),
+ displayText: '$parametersString =>',
+ selectionOffset: expressionSelectionOffset,
+ ),
+ );
}
/// Add a suggestion for a [constructor]. If a [kind] is provided it will be
@@ -421,11 +518,16 @@
var returnType = _instantiateClassElement(enclosingClass);
var relevance =
_computeTopLevelRelevance(constructor, elementType: returnType);
- _add(_createSuggestion(constructor,
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ constructor,
completion: completion,
kind: kind,
prefix: prefix,
- relevance: relevance));
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion for a top-level [element]. If a [kind] is provided it
@@ -460,13 +562,14 @@
var completion = '$enumName.$constantName';
var relevance =
_computeTopLevelRelevance(constant, elementType: constant.type);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
constant,
completion: completion,
kind: CompletionSuggestionKind.IDENTIFIER,
prefix: prefix,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -479,8 +582,15 @@
String? prefix}) {
var relevance = _computeTopLevelRelevance(extension,
elementType: extension.extendedType);
- _add(_createSuggestion(extension,
- kind: kind, prefix: prefix, relevance: relevance));
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ extension,
+ kind: kind,
+ prefix: prefix,
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion for a [field]. If the field is being referenced with a
@@ -509,11 +619,12 @@
superMatches: superMatches,
inheritanceDistance: inheritanceDistance,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
field,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -522,11 +633,12 @@
void suggestFieldFormalParameter(FieldElement field) {
// TODO(brianwilkerson) Add a parameter (`bool includePrefix`) indicating
// whether to include the `this.` prefix in the completion.
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
field,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: Relevance.fieldFormalParameter,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -539,22 +651,24 @@
typeParameters: null,
parameters: '()',
returnType: 'void');
- _add(CompletionSuggestion(
- CompletionSuggestionKind.INVOCATION,
- Relevance.callFunction,
- FunctionElement.CALL_METHOD_NAME,
- FunctionElement.CALL_METHOD_NAME.length,
- 0,
- false,
- false,
- displayText: 'call()',
- element: element,
- returnType: 'void',
- parameterNames: [],
- parameterTypes: [],
- requiredParameterCount: 0,
- hasNamedParameters: false,
- ));
+ _addSuggestion(
+ CompletionSuggestion(
+ CompletionSuggestionKind.INVOCATION,
+ Relevance.callFunction,
+ FunctionElement.CALL_METHOD_NAME,
+ FunctionElement.CALL_METHOD_NAME.length,
+ 0,
+ false,
+ false,
+ displayText: 'call()',
+ element: element,
+ returnType: 'void',
+ parameterNames: [],
+ parameterTypes: [],
+ requiredParameterCount: 0,
+ hasNamedParameters: false,
+ ),
+ );
}
/// Add a suggestion for a [keyword]. The [offset] is the offset from the
@@ -574,8 +688,8 @@
contextType: contextType,
keyword: keywordFeature,
);
- _add(CompletionSuggestion(CompletionSuggestionKind.KEYWORD, relevance,
- keyword, offset ?? keyword.length, 0, false, false));
+ _addSuggestion(CompletionSuggestion(CompletionSuggestionKind.KEYWORD,
+ relevance, keyword, offset ?? keyword.length, 0, false, false));
}
/// Add a suggestion for a [label].
@@ -588,7 +702,7 @@
Relevance.label, completion, completion.length, 0, false, false);
suggestion.element = createLocalElement(
request.source, protocol.ElementKind.LABEL, label.label);
- _add(suggestion);
+ _addSuggestion(suggestion);
}
}
@@ -598,11 +712,12 @@
// TODO(brianwilkerson) This might want to use the context type rather than
// a fixed value.
var relevance = Relevance.loadLibrary;
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
function,
kind: CompletionSuggestionKind.INVOCATION,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -628,11 +743,12 @@
isConstant: isConstant,
localVariableDistance: localVariableDistance,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
variable,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -675,46 +791,55 @@
inheritanceDistance: inheritanceDistance,
);
- var suggestion =
- _createSuggestion(method, kind: kind, relevance: relevance);
- if (suggestion != null) {
- var enclosingElement = method.enclosingElement;
- if (method.name == 'setState' &&
- enclosingElement is ClassElement &&
- flutter.isExactState(enclosingElement)) {
- // TODO(brianwilkerson) Make this more efficient by creating the correct
- // suggestion in the first place.
- // Find the line indentation.
- var indent = getRequestLineIndent(request);
+ var enclosingElement = method.enclosingElement;
+ if (method.name == 'setState' &&
+ enclosingElement is ClassElement &&
+ flutter.isExactState(enclosingElement)) {
+ // TODO(brianwilkerson) Make this more efficient by creating the correct
+ // suggestion in the first place.
+ // Find the line indentation.
+ var indent = getRequestLineIndent(request);
- // Let the user know that we are going to insert a complete statement.
- suggestion.displayText = 'setState(() {});';
+ // Build the completion and the selection offset.
+ var buffer = StringBuffer();
+ buffer.writeln('setState(() {');
+ buffer.write('$indent ');
+ var selectionOffset = buffer.length;
+ buffer.writeln();
+ buffer.write('$indent});');
- // Build the completion and the selection offset.
- var buffer = StringBuffer();
- buffer.writeln('setState(() {');
- buffer.write('$indent ');
- suggestion.selectionOffset = buffer.length;
- buffer.writeln();
- buffer.write('$indent});');
- suggestion.completion = buffer.toString();
-
- // There are no arguments to fill.
- suggestion.parameterNames = null;
- suggestion.parameterTypes = null;
- suggestion.requiredParameterCount = null;
- suggestion.hasNamedParameters = null;
- }
- _add(suggestion);
+ _addSuggestion(
+ CompletionSuggestion(
+ kind,
+ relevance,
+ buffer.toString(),
+ selectionOffset,
+ 0,
+ false,
+ false,
+ // Let the user know that we are going to insert a complete statement.
+ displayText: 'setState(() {});',
+ ),
+ );
+ return;
}
+
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ method,
+ kind: kind,
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion to use the [name] at a declaration site.
void suggestName(String name) {
// TODO(brianwilkerson) Explore whether there are any features of the name
// that can be used to provide better relevance scores.
- _add(CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER, 500, name,
- name.length, 0, false, false));
+ _addSuggestion(CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER,
+ 500, name, name.length, 0, false, false));
}
/// Add a suggestion to add a named argument corresponding to the [parameter].
@@ -783,7 +908,8 @@
suggestion.element =
convertElement(parameter, withNullability: _isNonNullableByDefault);
}
- _add(suggestion);
+
+ _addSuggestion(suggestion);
}
/// Add a suggestion to replace the [targetId] with an override of the given
@@ -842,7 +968,7 @@
displayText: displayText);
suggestion.element = protocol.convertElement(element,
withNullability: _isNonNullableByDefault);
- _add(suggestion);
+ _addSuggestion(suggestion);
}
/// Add a suggestion for a [parameter].
@@ -861,11 +987,12 @@
elementKind: elementKind,
isConstant: isConstant,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
parameter,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -879,19 +1006,25 @@
var relevance = _computeRelevance(
elementKind: elementKind,
);
- _add(_createSuggestion(library,
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ library,
completion: prefix,
kind: CompletionSuggestionKind.IDENTIFIER,
- relevance: relevance));
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion to reference a [parameter] in a super formal parameter.
void suggestSuperFormalParameter(ParameterElement parameter) {
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
parameter,
kind: CompletionSuggestionKind.IDENTIFIER,
relevance: Relevance.superFormalParameter,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -904,8 +1037,15 @@
String? prefix}) {
var relevance =
_computeTopLevelRelevance(function, elementType: function.returnType);
- _add(_createSuggestion(function,
- kind: kind, prefix: prefix, relevance: relevance));
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ function,
+ kind: kind,
+ prefix: prefix,
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion for a top-level property [accessor]. If a [kind] is
@@ -951,12 +1091,13 @@
startsWithDollar: startsWithDollar,
superMatches: superMatches,
);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
accessor,
kind: CompletionSuggestionKind.IDENTIFIER,
prefix: prefix,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -970,12 +1111,13 @@
assert(variable.enclosingElement is CompilationUnitElement);
var relevance =
_computeTopLevelRelevance(variable, elementType: variable.type);
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
variable,
kind: CompletionSuggestionKind.IDENTIFIER,
prefix: prefix,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -986,12 +1128,13 @@
void suggestTypeAlias(TypeAliasElement typeAlias, {String? prefix}) {
var relevance = _computeTopLevelRelevance(typeAlias,
elementType: _instantiateTypeAlias(typeAlias));
- _add(
- _createSuggestion(
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
typeAlias,
kind: CompletionSuggestionKind.IDENTIFIER,
prefix: prefix,
relevance: relevance,
+ isNotImported: isNotImportedLibrary,
),
);
}
@@ -1006,34 +1149,46 @@
elementKind: elementKind,
isConstant: isConstant,
);
- _add(_createSuggestion(parameter,
- kind: CompletionSuggestionKind.IDENTIFIER, relevance: relevance));
+ _addBuilder(
+ _createCompletionSuggestionBuilder(
+ parameter,
+ kind: CompletionSuggestionKind.IDENTIFIER,
+ relevance: relevance,
+ isNotImported: isNotImportedLibrary,
+ ),
+ );
}
/// Add a suggestion to use the [uri] in an import, export, or part directive.
void suggestUri(String uri) {
var relevance =
uri == 'dart:core' ? Relevance.importDartCore : Relevance.import;
- _add(CompletionSuggestion(CompletionSuggestionKind.IMPORT, relevance, uri,
- uri.length, 0, false, false));
+ _addSuggestion(
+ CompletionSuggestion(CompletionSuggestionKind.IMPORT, relevance, uri,
+ uri.length, 0, false, false),
+ );
}
/// Add the given [suggestion] if it isn't `null` and if it isn't shadowed by
/// a previously added suggestion.
- void _add(protocol.CompletionSuggestion? suggestion) {
+ void _addBuilder(CompletionSuggestionBuilder? suggestion) {
if (suggestion != null) {
- var key = suggestion.completion;
- if (suggestion.element?.kind == protocol.ElementKind.CONSTRUCTOR) {
- key = '$key()';
- }
+ var key = suggestion.key;
listener?.builtSuggestion(suggestion);
if (laterReplacesEarlier || !_suggestionMap.containsKey(key)) {
_suggestionMap[key] = suggestion;
- suggestionAdded?.call(suggestion);
}
}
}
+ /// Add the given [suggestion] if it isn't shadowed by a previously added
+ /// suggestion.
+ void _addSuggestion(protocol.CompletionSuggestion suggestion) {
+ _addBuilder(
+ ValueCompletionSuggestionBuilder(suggestion),
+ );
+ }
+
/// Compute the value of the _element kind_ feature for the given [element] in
/// the completion context.
double _computeElementKind(Element element, {double? distance}) {
@@ -1119,112 +1274,174 @@
);
}
- /// Return a suggestion based on the [element], or `null` if a suggestion is
- /// not appropriate for the element. If the completion should be something
+ /// Return a [CompletionSuggestionBuilder] based on the [element], or `null`
+ /// if the element cannot be suggested. If the completion should be something
/// different than the name of the element, then the [completion] should be
/// supplied. If an [elementKind] is provided, then it will be used rather
/// than the kind normally used for the element. If a [prefix] is provided,
/// then the element name (or completion) will be prefixed. The [relevance] is
/// the relevance of the suggestion.
- CompletionSuggestion? _createSuggestion(Element element,
- {String? completion,
- protocol.ElementKind? elementKind,
- required CompletionSuggestionKind kind,
- String? prefix,
- required int relevance}) {
- var inputs = _CompletionSuggestionInputs(
- completion: completion,
- elementKind: elementKind,
- kind: kind,
- prefix: prefix,
- );
-
- var cacheEntry = _elementSuggestionCache[element];
- if (cacheEntry != null) {
- if (cacheEntry.inputs == inputs) {
- final suggestion = cacheEntry.suggestion;
- suggestion.relevance = relevance;
- return suggestion;
- }
- }
-
- var suggestion = _createSuggestion0(
+ ///
+ /// TODO(scheglov) Consider removing [elementKind]
+ CompletionSuggestionBuilder? _createCompletionSuggestionBuilder(
+ Element element, {
+ String? completion,
+ protocol.ElementKind? elementKind,
+ required CompletionSuggestionKind kind,
+ required int relevance,
+ required bool isNotImported,
+ String? prefix,
+ }) {
+ var elementData = _getElementCompletionData(
element,
- completion: completion,
elementKind: elementKind,
- kind: kind,
- prefix: prefix,
- relevance: relevance,
);
- if (suggestion == null) {
+ if (elementData == null) {
return null;
}
- _elementSuggestionCache[element] = _CompletionSuggestionEntry(
- inputs: inputs,
- suggestion: suggestion,
+ if (prefix != null) {
+ completion ??= elementData.completion;
+ completion = prefix + '.' + completion;
+ }
+
+ return CompletionSuggestionBuilderImpl(
+ element: elementData,
+ kind: kind,
+ completionOverride: completion,
+ relevance: relevance,
+ libraryUriStr: libraryUriStr,
+ isNotImported: isNotImported,
);
- return suggestion;
}
- /// The non-caching implementation of [_createSuggestion].
- CompletionSuggestion? _createSuggestion0(
+ /// The non-caching implementation of [_getElementCompletionData].
+ ElementCompletionData? _createElementCompletionData(
Element element, {
- required String? completion,
- required protocol.ElementKind? elementKind,
- required CompletionSuggestionKind kind,
- required String? prefix,
- required int relevance,
+ protocol.ElementKind? elementKind,
}) {
+ // Do not include operators in suggestions.
if (element is ExecutableElement && element.isOperator) {
- // Do not include operators in suggestions
return null;
}
- completion ??= element.displayName;
- if (completion.isEmpty) {
- return null;
- }
- if (prefix != null && prefix.isNotEmpty) {
- completion = '$prefix.$completion';
- }
- var suggestion = CompletionSuggestion(kind, relevance, completion,
- completion.length, 0, element.hasOrInheritsDeprecated, false);
- _setDocumentation(suggestion, element);
- var suggestedElement = suggestion.element = protocol.convertElement(element,
+ var completion = element.displayName;
+ var documentation = _getDocumentation(element);
+
+ var suggestedElement = protocol.convertElement(element,
withNullability: _isNonNullableByDefault);
+
+ // TODO(scheglov) Update a copy.
if (elementKind != null) {
suggestedElement.kind = elementKind;
}
+
var enclosingElement = element.enclosingElement;
+
+ String? declaringType;
if (enclosingElement is ClassElement) {
- suggestion.declaringType = enclosingElement.displayName;
+ declaringType = enclosingElement.displayName;
}
- suggestion.returnType =
- getReturnTypeString(element, withNullability: _isNonNullableByDefault);
+
+ var returnType = getReturnTypeString(
+ element,
+ withNullability: _isNonNullableByDefault,
+ );
+
+ List<String>? parameterNames;
+ List<String>? parameterTypes;
+ int? requiredParameterCount;
+ bool? hasNamedParameters;
+ CompletionDefaultArgumentList? defaultArgumentList;
if (element is ExecutableElement && element is! PropertyAccessorElement) {
- suggestion.parameterNames = element.parameters
- .map((ParameterElement parameter) => parameter.name)
- .toList();
- suggestion.parameterTypes =
- element.parameters.map((ParameterElement parameter) {
- var paramType = parameter.type;
- return paramType.getDisplayString(
- withNullability: _isNonNullableByDefault);
+ parameterNames = element.parameters.map((parameter) {
+ return parameter.name;
+ }).toList();
+ parameterTypes = element.parameters.map((ParameterElement parameter) {
+ return parameter.type.getDisplayString(
+ withNullability: _isNonNullableByDefault,
+ );
}).toList();
var requiredParameters = element.parameters
.where((ParameterElement param) => param.isRequiredPositional);
- suggestion.requiredParameterCount = requiredParameters.length;
+ requiredParameterCount = requiredParameters.length;
var namedParameters =
element.parameters.where((ParameterElement param) => param.isNamed);
- suggestion.hasNamedParameters = namedParameters.isNotEmpty;
+ hasNamedParameters = namedParameters.isNotEmpty;
- addDefaultArgDetails(
- suggestion, element, requiredParameters, namedParameters);
+ defaultArgumentList = computeCompletionDefaultArgumentList(
+ element, requiredParameters, namedParameters);
}
- return suggestion;
+
+ return ElementCompletionData(
+ completion: completion,
+ isDeprecated: element.hasOrInheritsDeprecated,
+ declaringType: declaringType,
+ returnType: returnType,
+ parameterNames: parameterNames,
+ parameterTypes: parameterTypes,
+ requiredParameterCount: requiredParameterCount,
+ hasNamedParameters: hasNamedParameters,
+ documentation: documentation,
+ defaultArgumentList: defaultArgumentList,
+ element: suggestedElement,
+ );
+ }
+
+ /// If the [element] has a documentation comment, return it.
+ _ElementDocumentation? _getDocumentation(Element element) {
+ var documentationCache = request.documentationCache;
+ var data = documentationCache?.dataFor(element);
+ if (data != null) {
+ return _ElementDocumentation(
+ full: data.full,
+ summary: data.summary,
+ );
+ }
+ var doc = DartUnitHoverComputer.computeDocumentation(
+ request.dartdocDirectiveInfo,
+ element,
+ includeSummary: true,
+ );
+ if (doc is DocumentationWithSummary) {
+ return _ElementDocumentation(
+ full: doc.full,
+ summary: doc.summary,
+ );
+ }
+ if (doc is Documentation) {
+ return _ElementDocumentation(
+ full: doc.full,
+ summary: null,
+ );
+ }
+ return null;
+ }
+
+ /// Return [ElementCompletionData] for the [element], or `null` if the
+ /// element cannot be suggested for completion.
+ ///
+ /// TODO(scheglov) Consider removing [elementKind]
+ ElementCompletionData? _getElementCompletionData(
+ Element element, {
+ protocol.ElementKind? elementKind,
+ }) {
+ ElementCompletionData? result;
+
+ var hasCompletionData = element.ifTypeOrNull<HasCompletionData>();
+ if (hasCompletionData != null) {
+ result = hasCompletionData.completionData.ifTypeOrNull();
+ }
+
+ result ??= _createElementCompletionData(
+ element,
+ elementKind: elementKind,
+ );
+
+ hasCompletionData?.completionData = result;
+ return result;
}
/// Return the type associated with the [accessor], maybe `null` if an
@@ -1300,7 +1517,7 @@
abstract class SuggestionListener {
/// Invoked when a suggestion has been built.
- void builtSuggestion(protocol.CompletionSuggestion suggestion);
+ void builtSuggestion(CompletionSuggestionBuilder suggestionBuilder);
/// Invoked with the values of the features that were computed in the process
/// of building a suggestion. This method is invoked prior to invoking
@@ -1329,80 +1546,44 @@
void missingElementKindTableFor(String completionLocation);
}
-/// The entry of the element to suggestion cache.
-class _CompletionSuggestionEntry {
- final _CompletionSuggestionInputs inputs;
+/// [CompletionSuggestionBuilder] that is based on a [CompletionSuggestion].
+class ValueCompletionSuggestionBuilder implements CompletionSuggestionBuilder {
+ final CompletionSuggestion _suggestion;
- /// The suggestion computed for the element and [inputs].
- final CompletionSuggestion suggestion;
-
- _CompletionSuggestionEntry({
- required this.inputs,
- required this.suggestion,
- });
-}
-
-/// The inputs, other than the [Element], that were provided to create an
-/// instance of [CompletionSuggestion].
-class _CompletionSuggestionInputs {
- final String? completion;
- final protocol.ElementKind? elementKind;
- final CompletionSuggestionKind kind;
- final String? prefix;
-
- _CompletionSuggestionInputs({
- required this.completion,
- required this.elementKind,
- required this.kind,
- required this.prefix,
- });
+ ValueCompletionSuggestionBuilder(this._suggestion);
@override
- bool operator ==(Object other) {
- return other is _CompletionSuggestionInputs &&
- other.completion == completion &&
- other.elementKind == elementKind &&
- other.kind == kind &&
- other.prefix == prefix;
+ String get completion => _suggestion.completion;
+
+ @override
+ String get key => completion;
+
+ @override
+ protocol.CompletionSuggestionKind get kind => _suggestion.kind;
+
+ @override
+ int get relevance => _suggestion.relevance;
+
+ @override
+ CompletionSuggestion build() {
+ return _suggestion;
}
}
-extension CompletionSuggestionExtension on CompletionSuggestion {
- CompletionSuggestion copyWith({
- CopyWithValue<bool?>? isNotImported,
- }) {
- return protocol.CompletionSuggestion(
- kind,
- relevance,
- completion,
- selectionOffset,
- selectionLength,
- isDeprecated,
- isPotential,
- displayText: displayText,
- replacementOffset: replacementOffset,
- replacementLength: replacementLength,
- docSummary: docSummary,
- docComplete: docComplete,
- declaringType: declaringType,
- defaultArgumentListString: defaultArgumentListString,
- defaultArgumentListTextRanges: defaultArgumentListTextRanges,
- element: element,
- returnType: returnType,
- parameterNames: parameterNames,
- parameterTypes: parameterTypes,
- requiredParameterCount: requiredParameterCount,
- hasNamedParameters: hasNamedParameters,
- parameterName: parameterName,
- parameterType: parameterType,
- isNotImported: isNotImported.orElse(this.isNotImported),
- );
- }
+class _ElementDocumentation {
+ final String full;
+ final String? summary;
+
+ _ElementDocumentation({
+ required this.full,
+ required this.summary,
+ });
}
-extension _CopyWithValueExtension<T> on CopyWithValue<T>? {
- T orElse(T defaultValue) {
+extension on Object? {
+ /// If the target is [T], return it, otherwise `null`.
+ T? ifTypeOrNull<T>() {
final self = this;
- return self != null ? self.value : defaultValue;
+ return self is T ? self : null;
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index eef975c..279afd7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -25,13 +25,55 @@
return b.relevance.compareTo(a.relevance);
};
-/// Add default argument list text and ranges based on the given
+String buildClosureParameters(FunctionType type) {
+ var buffer = StringBuffer();
+ buffer.write('(');
+
+ var hasNamed = false;
+ var hasOptionalPositional = false;
+ var parameters = type.parameters;
+ var existingNames = parameters.map((p) => p.name).toSet();
+ for (var i = 0; i < parameters.length; ++i) {
+ var parameter = parameters[i];
+ if (i != 0) {
+ buffer.write(', ');
+ }
+ if (parameter.isNamed && !hasNamed) {
+ hasNamed = true;
+ buffer.write('{');
+ } else if (parameter.isOptionalPositional && !hasOptionalPositional) {
+ hasOptionalPositional = true;
+ buffer.write('[');
+ }
+ var name = parameter.name;
+ if (name.isEmpty) {
+ name = 'p$i';
+ var index = 1;
+ while (existingNames.contains(name)) {
+ name = 'p${i}_$index';
+ index++;
+ }
+ }
+ buffer.write(name);
+ }
+
+ if (hasNamed) {
+ buffer.write('}');
+ } else if (hasOptionalPositional) {
+ buffer.write(']');
+ }
+
+ buffer.write(')');
+ return buffer.toString();
+}
+
+/// Compute default argument list text and ranges based on the given
/// [requiredParams] and [namedParams].
-void addDefaultArgDetails(
- CompletionSuggestion suggestion,
- Element element,
- Iterable<ParameterElement> requiredParams,
- Iterable<ParameterElement> namedParams) {
+CompletionDefaultArgumentList computeCompletionDefaultArgumentList(
+ Element element,
+ Iterable<ParameterElement> requiredParams,
+ Iterable<ParameterElement> namedParams,
+) {
var sb = StringBuffer();
var ranges = <int>[];
@@ -95,50 +137,10 @@
}
}
- suggestion.defaultArgumentListString = sb.isNotEmpty ? sb.toString() : null;
- suggestion.defaultArgumentListTextRanges = ranges.isNotEmpty ? ranges : null;
-}
-
-String buildClosureParameters(FunctionType type) {
- var buffer = StringBuffer();
- buffer.write('(');
-
- var hasNamed = false;
- var hasOptionalPositional = false;
- var parameters = type.parameters;
- var existingNames = parameters.map((p) => p.name).toSet();
- for (var i = 0; i < parameters.length; ++i) {
- var parameter = parameters[i];
- if (i != 0) {
- buffer.write(', ');
- }
- if (parameter.isNamed && !hasNamed) {
- hasNamed = true;
- buffer.write('{');
- } else if (parameter.isOptionalPositional && !hasOptionalPositional) {
- hasOptionalPositional = true;
- buffer.write('[');
- }
- var name = parameter.name;
- if (name.isEmpty) {
- name = 'p$i';
- var index = 1;
- while (existingNames.contains(name)) {
- name = 'p${i}_$index';
- index++;
- }
- }
- buffer.write(name);
- }
-
- if (hasNamed) {
- buffer.write('}');
- } else if (hasOptionalPositional) {
- buffer.write(']');
- }
-
- buffer.write(')');
- return buffer.toString();
+ return CompletionDefaultArgumentList(
+ text: sb.isNotEmpty ? sb.toString() : null,
+ ranges: ranges.isNotEmpty ? ranges : null,
+ );
}
/// Create a new protocol Element for inclusion in a completion suggestion.
@@ -246,6 +248,16 @@
return type.getDisplayString(withNullability: false);
}
+class CompletionDefaultArgumentList {
+ final String? text;
+ final List<int>? ranges;
+
+ CompletionDefaultArgumentList({
+ required this.text,
+ required this.ranges,
+ });
+}
+
/// A tuple of text to insert and an (optional) location for the cursor.
class DefaultArgument {
/// The text to insert.
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 6f03e81..8b4050d 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -1162,10 +1162,14 @@
check(response).suggestions.matches([
(suggestion) => suggestion
..completion.isEqualTo('foo01')
- ..isGetter,
+ ..isGetter
+ ..libraryUri.isNull
+ ..isNotImported.isNull,
(suggestion) => suggestion
..completion.isEqualTo('foo02')
- ..isGetter,
+ ..isGetter
+ ..libraryUri.isNull
+ ..isNotImported.isNull,
]);
}
@@ -1609,6 +1613,29 @@
]);
}
+ Future<void> test_prefixed_importPrefix_class() async {
+ await _configureWithWorkspaceRoot();
+
+ var response = await _getTestCodeSuggestions('''
+import 'dart:math' as math;
+
+void f() {
+ math.Rand^
+}
+''');
+
+ check(response)
+ ..assertComplete()
+ ..hasReplacement(left: 4);
+
+ check(response).suggestions.withElementClass.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('Random')
+ ..libraryUri.isEqualTo('dart:math')
+ ..isNotImported.isNull,
+ ]);
+ }
+
Future<void> test_unprefixed_filters() async {
await _configureWithWorkspaceRoot();
@@ -1664,10 +1691,14 @@
check(response).suggestions.withElementClass.matches([
(suggestion) => suggestion
..completion.isEqualTo('A01')
- ..isClass,
+ ..isClass
+ ..libraryUri.isEqualTo('package:test/a.dart')
+ ..isNotImported.isNull,
(suggestion) => suggestion
..completion.isEqualTo('A02')
- ..isClass,
+ ..isClass
+ ..libraryUri.isEqualTo('package:test/b.dart')
+ ..isNotImported.isNull,
]);
}
@@ -1698,10 +1729,14 @@
check(response).suggestions.matches([
(suggestion) => suggestion
..completion.isEqualTo('foo01')
- ..isTopLevelVariable,
+ ..isTopLevelVariable
+ ..libraryUri.isEqualTo('package:test/a.dart')
+ ..isNotImported.isNull,
(suggestion) => suggestion
..completion.isEqualTo('foo02')
- ..isTopLevelVariable,
+ ..isTopLevelVariable
+ ..libraryUri.isEqualTo('package:test/b.dart')
+ ..isNotImported.isNull,
]);
}
@@ -1724,7 +1759,8 @@
check(response).suggestions.withElementClass.matches([
(suggestion) => suggestion
..completion.isEqualTo('math.Random')
- ..libraryUriToImport.isNull,
+ ..libraryUri.isEqualTo('dart:math')
+ ..isNotImported.isNull,
]);
}
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 1e7cde4..3e1ed40 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -305,6 +305,7 @@
'hasNamedParameters': isBool,
'parameterName': isString,
'parameterType': isString,
+ 'libraryUri': isString,
'isNotImported': isBool
}));
@@ -384,8 +385,7 @@
'parameters': isString,
'returnType': isString,
'typeParameters': isString,
- 'aliasedType': isString,
- 'libraryUri': isString
+ 'aliasedType': isString
}));
/// ElementDeclaration
diff --git a/pkg/analysis_server/test/search/type_hierarchy_test.dart b/pkg/analysis_server/test/search/type_hierarchy_test.dart
index 28f9cba..2ed436f 100644
--- a/pkg/analysis_server/test/search/type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/search/type_hierarchy_test.dart
@@ -64,8 +64,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -77,8 +76,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -118,8 +116,7 @@
'kind': 'CLASS',
'name': 'AAA',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -131,8 +128,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -143,8 +139,7 @@
'kind': 'CLASS',
'name': 'BBB',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -156,8 +151,7 @@
'kind': 'CLASS',
'name': 'CCC',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -210,8 +204,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -223,8 +216,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -235,8 +227,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -248,8 +239,7 @@
'kind': 'CLASS',
'name': 'C',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 2,
'interfaces': [],
@@ -275,8 +265,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -288,8 +277,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 2,
'interfaces': [],
@@ -301,8 +289,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -313,8 +300,7 @@
'kind': 'CLASS',
'name': 'C',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -340,8 +326,7 @@
'kind': 'CLASS',
'name': 'C',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -353,8 +338,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 2,
'interfaces': [],
@@ -366,8 +350,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 3,
'interfaces': [],
@@ -379,8 +362,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -405,8 +387,7 @@
'kind': 'CLASS',
'name': 'T',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [2, 3],
@@ -418,8 +399,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -430,8 +410,7 @@
'kind': 'CLASS',
'name': 'MA',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -443,8 +422,7 @@
'kind': 'CLASS',
'name': 'MB',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -471,8 +449,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -484,8 +461,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -496,8 +472,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -509,8 +484,7 @@
'kind': 'CLASS',
'name': 'C',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -522,8 +496,7 @@
'kind': 'CLASS',
'name': 'D',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -535,8 +508,7 @@
'kind': 'CLASS',
'name': 'E',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 0,
'interfaces': [],
@@ -548,8 +520,7 @@
'kind': 'CLASS',
'name': 'F',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 4,
'interfaces': [],
@@ -561,8 +532,7 @@
'kind': 'CLASS',
'name': 'G',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 4,
'interfaces': [],
@@ -588,8 +558,7 @@
'kind': 'CLASS',
'name': 'T',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -601,8 +570,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -613,8 +581,7 @@
'kind': 'CLASS',
'name': 'MA',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -626,8 +593,7 @@
'kind': 'CLASS',
'name': 'MB',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [],
@@ -1167,8 +1133,7 @@
'kind': 'CLASS',
'name': 'C',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 1,
'interfaces': [3],
@@ -1180,8 +1145,7 @@
'kind': 'CLASS',
'name': 'A',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 2,
'interfaces': [],
@@ -1193,8 +1157,7 @@
'kind': 'CLASS',
'name': 'Object',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'interfaces': [],
'mixins': [],
@@ -1205,8 +1168,7 @@
'kind': 'CLASS',
'name': 'B',
'location': anything,
- 'flags': 0,
- 'libraryUri': anything
+ 'flags': 0
},
'superclass': 2,
'interfaces': [],
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_check.dart b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
index 222d9dd..6ecb423 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_check.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
@@ -251,10 +251,18 @@
}
@useResult
+ CheckTarget<String?> get libraryUri {
+ return nest(
+ value.suggestion.libraryUri,
+ (selected) => 'has libraryUri ${valueStr(selected)}',
+ );
+ }
+
+ @useResult
CheckTarget<String?> get libraryUriToImport {
return nest(
value.suggestion.isNotImported == true
- ? value.suggestion.element?.libraryUri
+ ? value.suggestion.libraryUri
: null,
(selected) => 'has libraryUriToImport ${valueStr(selected)}',
);
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index f721cc8..c05f315 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -49,7 +49,7 @@
var builder = SuggestionBuilder(request);
var contributor = createContributor(request, builder);
await contributor.computeSuggestions();
- return builder.suggestions.toList();
+ return builder.suggestions.map((e) => e.build()).toList();
}
DartCompletionContributor createContributor(
diff --git a/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart b/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
index 9f66816..3ee46d5 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
@@ -33,7 +33,7 @@
);
var builder = SuggestionBuilder(request);
builder.suggestTopLevelFunction(findElement.topFunction('f'));
- var suggestions = builder.suggestions.toList();
+ var suggestions = builder.suggestions.map((e) => e.build()).toList();
expect(suggestions, hasLength(1));
return suggestions[0];
}
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart
index 2f7a688..301c2ad 100644
--- a/pkg/analysis_server/test/stress/completion/completion_runner.dart
+++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/utilities/null_string_sink.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
@@ -11,7 +12,6 @@
import 'package:analyzer/file_system/overlay_file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
/// A runner that can request code completion at the location of each identifier
/// in a Dart file.
@@ -203,8 +203,8 @@
}
}
- List<CompletionSuggestion> _filterBy(
- List<CompletionSuggestion> suggestions, String pattern) {
+ List<CompletionSuggestionBuilder> _filterBy(
+ List<CompletionSuggestionBuilder> suggestions, String pattern) {
return suggestions
.where((suggestion) => suggestion.completion.startsWith(pattern))
.toList();
@@ -220,7 +220,8 @@
/// If the given list of [suggestions] includes a suggestion for the given
/// [identifier], return the index of the suggestion. Otherwise, return `-1`.
- int _indexOf(List<CompletionSuggestion> suggestions, String identifier) {
+ int _indexOf(
+ List<CompletionSuggestionBuilder> suggestions, String identifier) {
for (var i = 0; i < suggestions.length; i++) {
if (suggestions[i].completion == identifier) {
return i;
@@ -237,7 +238,7 @@
}
/// Print information about the given [suggestions].
- void _printSuggestions(List<CompletionSuggestion> suggestions) {
+ void _printSuggestions(List<CompletionSuggestionBuilder> suggestions) {
if (suggestions.isEmpty) {
output.writeln(' No suggestions');
return;
@@ -248,7 +249,8 @@
}
}
- List<CompletionSuggestion> _sort(List<CompletionSuggestion> suggestions) {
+ List<CompletionSuggestionBuilder> _sort(
+ List<CompletionSuggestionBuilder> suggestions) {
suggestions.sort((first, second) => second.relevance - first.relevance);
return suggestions;
}
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index 7007b15..d6f8764 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1217,11 +1217,14 @@
var budget = CompletionBudget(Duration(seconds: 30));
if (declarationsTracker == null) {
// available suggestions == false
- suggestions = await DartCompletionManager(
- budget: budget,
- listener: listener,
- notImportedSuggestions: notImportedSuggestions)
- .computeSuggestions(dartRequest, performance);
+ var serverSuggestions = await DartCompletionManager(
+ budget: budget,
+ listener: listener,
+ notImportedSuggestions: notImportedSuggestions,
+ ).computeSuggestions(dartRequest, performance);
+ suggestions = serverSuggestions.map((serverSuggestion) {
+ return serverSuggestion.build();
+ }).toList();
} else {
// available suggestions == true
var includedElementKinds = <protocol.ElementKind>{};
@@ -1229,13 +1232,16 @@
var includedSuggestionRelevanceTagList =
<protocol.IncludedSuggestionRelevanceTag>[];
var includedSuggestionSetList = <protocol.IncludedSuggestionSet>[];
- suggestions = await DartCompletionManager(
+ var serverSuggestions = await DartCompletionManager(
budget: budget,
includedElementKinds: includedElementKinds,
includedElementNames: includedElementNames,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTagList,
listener: listener,
).computeSuggestions(dartRequest, performance);
+ suggestions = serverSuggestions.map((serverSuggestion) {
+ return serverSuggestion.build();
+ }).toList();
computeIncludedSetList(declarationsTracker, dartRequest,
includedSuggestionSetList, includedElementNames);
@@ -1923,7 +1929,8 @@
String? missingCompletionLocationTable;
@override
- void builtSuggestion(protocol.CompletionSuggestion suggestion) {
+ void builtSuggestion(CompletionSuggestionBuilder suggestionBuilder) {
+ var suggestion = suggestionBuilder.build();
featureMap[suggestion] = cachedFeatures;
cachedFeatures = noFeatures;
}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
index f73aa41..9bc6c74 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
@@ -176,6 +176,21 @@
private final String parameterType;
/**
+ * This field is omitted if getSuggestions was used rather than getSuggestions2.
+ *
+ * This field is omitted if this suggestion corresponds to a locally declared element.
+ *
+ * If this suggestion corresponds to an already imported element, then this field is the URI of a
+ * library that provides this element, not the URI of the library where the element is declared.
+ *
+ * If this suggestion corresponds to an element from a not yet imported library, this field is the
+ * URI of a library that could be imported to make this suggestion accessible in the file where
+ * completion was requested, such as package:foo/bar.dart or
+ * file:///home/me/workspace/foo/test/bar_test.dart.
+ */
+ private final String libraryUri;
+
+ /**
* True if the suggestion is for an element from a not yet imported library. This field is omitted
* if the element is declared locally, or is from library is already imported, so that the
* suggestion can be inserted as is, or if getSuggestions was used rather than getSuggestions2.
@@ -185,7 +200,7 @@
/**
* Constructor for {@link CompletionSuggestion}.
*/
- public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, Boolean isNotImported) {
+ public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, String libraryUri, Boolean isNotImported) {
this.kind = kind;
this.relevance = relevance;
this.completion = completion;
@@ -209,6 +224,7 @@
this.hasNamedParameters = hasNamedParameters;
this.parameterName = parameterName;
this.parameterType = parameterType;
+ this.libraryUri = libraryUri;
this.isNotImported = isNotImported;
}
@@ -240,6 +256,7 @@
ObjectUtilities.equals(other.hasNamedParameters, hasNamedParameters) &&
ObjectUtilities.equals(other.parameterName, parameterName) &&
ObjectUtilities.equals(other.parameterType, parameterType) &&
+ ObjectUtilities.equals(other.libraryUri, libraryUri) &&
ObjectUtilities.equals(other.isNotImported, isNotImported);
}
return false;
@@ -269,8 +286,9 @@
Boolean hasNamedParameters = jsonObject.get("hasNamedParameters") == null ? null : jsonObject.get("hasNamedParameters").getAsBoolean();
String parameterName = jsonObject.get("parameterName") == null ? null : jsonObject.get("parameterName").getAsString();
String parameterType = jsonObject.get("parameterType") == null ? null : jsonObject.get("parameterType").getAsString();
+ String libraryUri = jsonObject.get("libraryUri") == null ? null : jsonObject.get("libraryUri").getAsString();
Boolean isNotImported = jsonObject.get("isNotImported") == null ? null : jsonObject.get("isNotImported").getAsBoolean();
- return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, isNotImported);
+ return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, libraryUri, isNotImported);
}
public static List<CompletionSuggestion> fromJsonArray(JsonArray jsonArray) {
@@ -391,6 +409,23 @@
}
/**
+ * This field is omitted if getSuggestions was used rather than getSuggestions2.
+ *
+ * This field is omitted if this suggestion corresponds to a locally declared element.
+ *
+ * If this suggestion corresponds to an already imported element, then this field is the URI of a
+ * library that provides this element, not the URI of the library where the element is declared.
+ *
+ * If this suggestion corresponds to an element from a not yet imported library, this field is the
+ * URI of a library that could be imported to make this suggestion accessible in the file where
+ * completion was requested, such as package:foo/bar.dart or
+ * file:///home/me/workspace/foo/test/bar_test.dart.
+ */
+ public String getLibraryUri() {
+ return libraryUri;
+ }
+
+ /**
* The name of the optional parameter being suggested. This field is omitted if the suggestion is
* not the addition of an optional argument within an argument list.
*/
@@ -505,6 +540,7 @@
builder.append(hasNamedParameters);
builder.append(parameterName);
builder.append(parameterType);
+ builder.append(libraryUri);
builder.append(isNotImported);
return builder.toHashCode();
}
@@ -578,6 +614,9 @@
if (parameterType != null) {
jsonObject.addProperty("parameterType", parameterType);
}
+ if (libraryUri != null) {
+ jsonObject.addProperty("libraryUri", libraryUri);
+ }
if (isNotImported != null) {
jsonObject.addProperty("isNotImported", isNotImported);
}
@@ -634,6 +673,8 @@
builder.append(parameterName + ", ");
builder.append("parameterType=");
builder.append(parameterType + ", ");
+ builder.append("libraryUri=");
+ builder.append(libraryUri + ", ");
builder.append("isNotImported=");
builder.append(isNotImported);
builder.append("]");
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Element.java b/pkg/analysis_server/tool/spec/generated/java/types/Element.java
index 0648fc7..690f101 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Element.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Element.java
@@ -101,15 +101,9 @@
private final String aliasedType;
/**
- * If the element belongs to a library, the URI of the library. Otherwise, this field will not be
- * defined.
- */
- private final String libraryUri;
-
- /**
* Constructor for {@link Element}.
*/
- public Element(String kind, String name, Location location, int flags, String parameters, String returnType, String typeParameters, String aliasedType, String libraryUri) {
+ public Element(String kind, String name, Location location, int flags, String parameters, String returnType, String typeParameters, String aliasedType) {
this.kind = kind;
this.name = name;
this.location = location;
@@ -118,7 +112,6 @@
this.returnType = returnType;
this.typeParameters = typeParameters;
this.aliasedType = aliasedType;
- this.libraryUri = libraryUri;
}
@Override
@@ -133,8 +126,7 @@
ObjectUtilities.equals(other.parameters, parameters) &&
ObjectUtilities.equals(other.returnType, returnType) &&
ObjectUtilities.equals(other.typeParameters, typeParameters) &&
- ObjectUtilities.equals(other.aliasedType, aliasedType) &&
- ObjectUtilities.equals(other.libraryUri, libraryUri);
+ ObjectUtilities.equals(other.aliasedType, aliasedType);
}
return false;
}
@@ -148,8 +140,7 @@
String returnType = jsonObject.get("returnType") == null ? null : jsonObject.get("returnType").getAsString();
String typeParameters = jsonObject.get("typeParameters") == null ? null : jsonObject.get("typeParameters").getAsString();
String aliasedType = jsonObject.get("aliasedType") == null ? null : jsonObject.get("aliasedType").getAsString();
- String libraryUri = jsonObject.get("libraryUri") == null ? null : jsonObject.get("libraryUri").getAsString();
- return new Element(kind, name, location, flags, parameters, returnType, typeParameters, aliasedType, libraryUri);
+ return new Element(kind, name, location, flags, parameters, returnType, typeParameters, aliasedType);
}
public static List<Element> fromJsonArray(JsonArray jsonArray) {
@@ -194,14 +185,6 @@
}
/**
- * If the element belongs to a library, the URI of the library. Otherwise, this field will not be
- * defined.
- */
- public String getLibraryUri() {
- return libraryUri;
- }
-
- /**
* The location of the name in the declaration of the element.
*/
public Location getLocation() {
@@ -252,7 +235,6 @@
builder.append(returnType);
builder.append(typeParameters);
builder.append(aliasedType);
- builder.append(libraryUri);
return builder.toHashCode();
}
@@ -300,9 +282,6 @@
if (aliasedType != null) {
jsonObject.addProperty("aliasedType", aliasedType);
}
- if (libraryUri != null) {
- jsonObject.addProperty("libraryUri", libraryUri);
- }
return jsonObject;
}
@@ -325,9 +304,7 @@
builder.append("typeParameters=");
builder.append(typeParameters + ", ");
builder.append("aliasedType=");
- builder.append(aliasedType + ", ");
- builder.append("libraryUri=");
- builder.append(libraryUri);
+ builder.append(aliasedType);
builder.append("]");
return builder.toString();
}
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
index c1a528b..71431b4 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -612,6 +612,23 @@
/// if the parameterName field is omitted.
String? parameterType;
+ /// This field is omitted if getSuggestions was used rather than
+ /// getSuggestions2.
+ ///
+ /// This field is omitted if this suggestion corresponds to a locally
+ /// declared element.
+ ///
+ /// If this suggestion corresponds to an already imported element, then this
+ /// field is the URI of a library that provides this element, not the URI of
+ /// the library where the element is declared.
+ ///
+ /// If this suggestion corresponds to an element from a not yet imported
+ /// library, this field is the URI of a library that could be imported to
+ /// make this suggestion accessible in the file where completion was
+ /// requested, such as package:foo/bar.dart or
+ /// file:///home/me/workspace/foo/test/bar_test.dart.
+ String? libraryUri;
+
/// True if the suggestion is for an element from a not yet imported library.
/// This field is omitted if the element is declared locally, or is from
/// library is already imported, so that the suggestion can be inserted as
@@ -642,6 +659,7 @@
this.hasNamedParameters,
this.parameterName,
this.parameterType,
+ this.libraryUri,
this.isNotImported});
factory CompletionSuggestion.fromJson(
@@ -781,6 +799,11 @@
parameterType = jsonDecoder.decodeString(
jsonPath + '.parameterType', json['parameterType']);
}
+ String? libraryUri;
+ if (json.containsKey('libraryUri')) {
+ libraryUri = jsonDecoder.decodeString(
+ jsonPath + '.libraryUri', json['libraryUri']);
+ }
bool? isNotImported;
if (json.containsKey('isNotImported')) {
isNotImported = jsonDecoder.decodeBool(
@@ -804,6 +827,7 @@
hasNamedParameters: hasNamedParameters,
parameterName: parameterName,
parameterType: parameterType,
+ libraryUri: libraryUri,
isNotImported: isNotImported);
} else {
throw jsonDecoder.mismatch(jsonPath, 'CompletionSuggestion', json);
@@ -884,6 +908,10 @@
if (parameterType != null) {
result['parameterType'] = parameterType;
}
+ var libraryUri = this.libraryUri;
+ if (libraryUri != null) {
+ result['libraryUri'] = libraryUri;
+ }
var isNotImported = this.isNotImported;
if (isNotImported != null) {
result['isNotImported'] = isNotImported;
@@ -923,6 +951,7 @@
hasNamedParameters == other.hasNamedParameters &&
parameterName == other.parameterName &&
parameterType == other.parameterType &&
+ libraryUri == other.libraryUri &&
isNotImported == other.isNotImported;
}
return false;
@@ -953,6 +982,7 @@
hasNamedParameters,
parameterName,
parameterType,
+ libraryUri,
isNotImported,
]);
}
@@ -1234,17 +1264,12 @@
/// this field will not be defined.
String? aliasedType;
- /// If the element belongs to a library, the URI of the library. Otherwise,
- /// this field will not be defined.
- String? libraryUri;
-
Element(this.kind, this.name, this.flags,
{this.location,
this.parameters,
this.returnType,
this.typeParameters,
- this.aliasedType,
- this.libraryUri});
+ this.aliasedType});
factory Element.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -1294,18 +1319,12 @@
aliasedType = jsonDecoder.decodeString(
jsonPath + '.aliasedType', json['aliasedType']);
}
- String? libraryUri;
- if (json.containsKey('libraryUri')) {
- libraryUri = jsonDecoder.decodeString(
- jsonPath + '.libraryUri', json['libraryUri']);
- }
return Element(kind, name, flags,
location: location,
parameters: parameters,
returnType: returnType,
typeParameters: typeParameters,
- aliasedType: aliasedType,
- libraryUri: libraryUri);
+ aliasedType: aliasedType);
} else {
throw jsonDecoder.mismatch(jsonPath, 'Element', json);
}
@@ -1344,10 +1363,6 @@
if (aliasedType != null) {
result['aliasedType'] = aliasedType;
}
- var libraryUri = this.libraryUri;
- if (libraryUri != null) {
- result['libraryUri'] = libraryUri;
- }
return result;
}
@@ -1364,8 +1379,7 @@
parameters == other.parameters &&
returnType == other.returnType &&
typeParameters == other.typeParameters &&
- aliasedType == other.aliasedType &&
- libraryUri == other.libraryUri;
+ aliasedType == other.aliasedType;
}
return false;
}
@@ -1380,7 +1394,6 @@
returnType,
typeParameters,
aliasedType,
- libraryUri,
);
}
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 14a910c..487f5f95 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -104,8 +104,10 @@
CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD,
CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS,
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_ENUM,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_CLASS,
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_MIXIN,
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MIXIN,
diff --git a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
index 103c1a6..2f3fd34 100644
--- a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
@@ -14,7 +14,7 @@
import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
-import 'package:cli_util/cli_util.dart';
+import 'package:analyzer/src/util/sdk.dart';
/// An implementation of [AnalysisContextCollection].
class AnalysisContextCollectionImpl implements AnalysisContextCollection {
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index a9c0df3..e1ae643 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -27,8 +27,8 @@
import 'package:analyzer/src/summary/summary_sdk.dart';
import 'package:analyzer/src/summary2/package_bundle_format.dart';
import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer/src/workspace/workspace.dart';
-import 'package:cli_util/cli_util.dart';
/// An implementation of a context builder.
class ContextBuilderImpl implements ContextBuilder {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index b0f4037..a5e5f49 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -46,7 +46,7 @@
/// A concrete implementation of a [ClassElement].
abstract class AbstractClassElementImpl extends _ExistingElementImpl
- with TypeParameterizedElementMixin
+ with TypeParameterizedElementMixin, HasCompletionData
implements ClassElement {
/// The superclass of the class, or `null` for [Object].
InterfaceType? _supertype;
@@ -2803,7 +2803,7 @@
/// A base class for concrete implementations of an [ExecutableElement].
abstract class ExecutableElementImpl extends _ExistingElementImpl
- with TypeParameterizedElementMixin
+ with TypeParameterizedElementMixin, HasCompletionData
implements ExecutableElement, ElementImplWithFunctionType {
/// A list containing all of the parameters defined by this executable
/// element.
@@ -3474,6 +3474,11 @@
}
}
+/// This mixins is added to elements that can have cache completion data.
+mixin HasCompletionData {
+ Object? completionData;
+}
+
/// A concrete implementation of a [HideElementCombinator].
class HideElementCombinatorImpl implements HideElementCombinator {
@override
@@ -5103,12 +5108,12 @@
@override
Element get nonSynthetic {
- if (enclosingElement is EnumElementImpl) {
- if (name == 'index' || name == 'values') {
- return enclosingElement;
- }
+ final variable = this.variable;
+ if (!variable.isSynthetic) {
+ return variable;
}
- return variable;
+ assert(enclosingElement is EnumElementImpl);
+ return enclosingElement;
}
@override
@@ -5435,6 +5440,7 @@
/// A concrete implementation of a [TopLevelVariableElement].
class TopLevelVariableElementImpl extends PropertyInducingElementImpl
+ with HasCompletionData
implements TopLevelVariableElement {
/// Initialize a newly created synthetic top-level variable element to have
/// the given [name] and [offset].
diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart
index 6cccc05..a9c1500 100644
--- a/pkg/analyzer/lib/src/error/codes.g.dart
+++ b/pkg/analyzer/lib/src/error/codes.g.dart
@@ -1886,6 +1886,20 @@
* Parameters:
* 0: the name of the type variable
*/
+ static const CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_ENUM =
+ CompileTimeErrorCode(
+ 'CONFLICTING_TYPE_VARIABLE_AND_CONTAINER',
+ "'{0}' can't be used to name both a type variable and the enum in which "
+ "the type variable is defined.",
+ correctionMessage: "Try renaming either the type variable or the enum.",
+ hasPublishedDocs: true,
+ uniqueName: 'CONFLICTING_TYPE_VARIABLE_AND_ENUM',
+ );
+
+ /**
+ * Parameters:
+ * 0: the name of the type variable
+ */
static const CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_EXTENSION =
CompileTimeErrorCode(
'CONFLICTING_TYPE_VARIABLE_AND_CONTAINER',
@@ -1941,6 +1955,20 @@
* Parameters:
* 0: the name of the type variable
*/
+ static const CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM =
+ CompileTimeErrorCode(
+ 'CONFLICTING_TYPE_VARIABLE_AND_MEMBER',
+ "'{0}' can't be used to name both a type variable and a member in this "
+ "enum.",
+ correctionMessage: "Try renaming either the type variable or the member.",
+ hasPublishedDocs: true,
+ uniqueName: 'CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM',
+ );
+
+ /**
+ * Parameters:
+ * 0: the name of the type variable
+ */
static const CompileTimeErrorCode
CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION = CompileTimeErrorCode(
'CONFLICTING_TYPE_VARIABLE_AND_MEMBER',
@@ -14215,8 +14243,8 @@
/**
* Parameters:
- * 0: the name of the enumeration constant that is not defined
- * 1: the name of the enumeration used to access the constant
+ * 0: the name of the enum constant that is not defined
+ * 1: the name of the enum used to access the constant
*/
// #### Description
//
@@ -16450,7 +16478,7 @@
// #### Description
//
// The analyzer produces this diagnostic when a `switch` statement for an enum
- // doesn't include an option for one of the values in the enumeration.
+ // doesn't include an option for one of the values in the enum.
//
// Note that `null` is always a possible value for an enum and therefore also
// must be handled.
diff --git a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
index 2978a39..00fadde 100644
--- a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
+++ b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
@@ -40,6 +40,11 @@
_initFieldsMap(node.declaredElement!);
}
+ void enterEnum(EnumDeclaration node) {
+ _isInNativeClass = false;
+ _initFieldsMap(node.declaredElement!);
+ }
+
void leaveClass() {
_isInNativeClass = false;
_initialFieldMap = null;
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 113dae0..08b53b9 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -8,21 +8,20 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/error/codes.dart';
class DuplicateDefinitionVerifier {
- static final Set<String> _enumInstanceMembers = {
- 'hashCode',
- 'index',
- FunctionElement.NO_SUCH_METHOD_METHOD_NAME,
- 'runtimeType',
- 'toString',
- };
-
+ final InheritanceManager3 _inheritanceManager;
final LibraryElement _currentLibrary;
final ErrorReporter _errorReporter;
- DuplicateDefinitionVerifier(this._currentLibrary, this._errorReporter);
+ DuplicateDefinitionVerifier(
+ this._inheritanceManager,
+ this._currentLibrary,
+ this._errorReporter,
+ );
/// Check that the exception and stack trace parameters have different names.
void checkCatchClause(CatchClause node) {
@@ -45,30 +44,65 @@
/// Check that there are no members with the same name.
void checkEnum(EnumDeclaration node) {
- ClassElement element = node.declaredElement!;
+ var enumElement = node.declaredElement as EnumElementImpl;
+ var enumName = enumElement.name;
- Map<String, Element> staticGetters = {
- 'values': element.getGetter('values')!
- };
+ var instanceGetters = <String, Element>{};
+ var instanceSetters = <String, Element>{};
+ var staticGetters = <String, Element>{};
+ var staticSetters = <String, Element>{};
for (EnumConstantDeclaration constant in node.constants) {
_checkDuplicateIdentifier(staticGetters, constant.name);
}
- String enumName = element.name;
- for (EnumConstantDeclaration constant in node.constants) {
- SimpleIdentifier identifier = constant.name;
- String name = identifier.name;
- if (name == enumName) {
+ for (var member in node.members) {
+ if (member is FieldDeclaration) {
+ for (var field in member.fields.variables) {
+ var identifier = field.name;
+ _checkDuplicateIdentifier(
+ member.isStatic ? staticGetters : instanceGetters,
+ identifier,
+ setterScope: member.isStatic ? staticSetters : instanceSetters,
+ );
+ }
+ } else if (member is MethodDeclaration) {
+ _checkDuplicateIdentifier(
+ member.isStatic ? staticGetters : instanceGetters,
+ member.name,
+ setterScope: member.isStatic ? staticSetters : instanceSetters,
+ );
+ }
+ }
+
+ for (var constant in node.constants) {
+ if (constant.name.name == enumName) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING,
- identifier,
+ constant.name,
);
- } else if (_enumInstanceMembers.contains(name)) {
- _errorReporter.reportErrorForNode(
+ }
+ }
+
+ var staticExecutable = [
+ ...enumElement.accessors,
+ ...enumElement.methods,
+ ].where((element) => element.isStatic);
+ for (var executable in staticExecutable) {
+ var baseName = executable.displayName;
+ var instanceGetter = _inheritanceManager.getMember2(
+ enumElement,
+ Name(_currentLibrary.source.uri, baseName),
+ );
+ var instanceSetter = _inheritanceManager.getMember2(
+ enumElement,
+ Name(_currentLibrary.source.uri, '$baseName='),
+ );
+ if (instanceGetter != null || instanceSetter != null) {
+ _errorReporter.reportErrorForElement(
CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
- identifier,
- [enumName, name, enumName],
+ executable,
+ [enumName, baseName, enumName],
);
}
}
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 233fb5f..42cca4f 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -246,8 +246,8 @@
_UninstantiatedBoundChecker(errorReporter),
_checkUseVerifier = UseResultVerifier(errorReporter),
_requiredParametersVerifier = RequiredParametersVerifier(errorReporter),
- _duplicateDefinitionVerifier =
- DuplicateDefinitionVerifier(_currentLibrary, errorReporter) {
+ _duplicateDefinitionVerifier = DuplicateDefinitionVerifier(
+ _inheritanceManager, _currentLibrary, errorReporter) {
_isInSystemLibrary = _currentLibrary.source.uri.isScheme('dart');
_isInCatchClause = false;
_isInStaticVariableDeclaration = false;
@@ -561,14 +561,13 @@
void visitEnumDeclaration(EnumDeclaration node) {
var outerClass = _enclosingClass;
try {
- _enclosingClass = node.declaredElement;
+ var element = node.declaredElement as EnumElementImpl;
+ _enclosingClass = element;
_duplicateDefinitionVerifier.checkEnum(node);
- // TODO(scheglov) implement
- // List<ClassMember> members = node.members;
_checkForBuiltInIdentifierAsName(
node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
- // _checkForConflictingClassTypeVariableErrorCodes();
+ _checkForConflictingEnumTypeVariableErrorCodes(element);
var implementsClause = node.implementsClause;
var withClause = node.withClause;
@@ -578,8 +577,8 @@
// TODO(scheglov) implement
// _checkForConflictingClassMembers();
- // _constructorFieldsVerifier.enterClass(node);
- // _checkForFinalNotInitializedInClass(members);
+ _constructorFieldsVerifier.enterEnum(node);
+ _checkForFinalNotInitializedInClass(node.members);
_checkForWrongTypeParameterVarianceInSuperinterfaces();
_checkForMainFunction(node.name);
@@ -1845,6 +1844,32 @@
}
}
+ void _checkForConflictingEnumTypeVariableErrorCodes(
+ EnumElementImpl element,
+ ) {
+ for (var typeParameter in element.typeParameters) {
+ var name = typeParameter.name;
+ // name is same as the name of the enclosing enum
+ if (element.name == name) {
+ errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_ENUM,
+ typeParameter,
+ [name],
+ );
+ }
+ // check members
+ if (element.getMethod(name) != null ||
+ element.getGetter(name) != null ||
+ element.getSetter(name) != null) {
+ errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM,
+ typeParameter,
+ [name],
+ );
+ }
+ }
+ }
+
/// Verify all conflicts between type variable and enclosing extension.
///
/// See [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION], and
diff --git a/pkg/analyzer/lib/src/util/sdk.dart b/pkg/analyzer/lib/src/util/sdk.dart
index d588cc3..6e73efb 100644
--- a/pkg/analyzer/lib/src/util/sdk.dart
+++ b/pkg/analyzer/lib/src/util/sdk.dart
@@ -6,27 +6,5 @@
import 'package:path/path.dart' as path;
-String getSdkPath([List<String>? args]) {
- // Look for --dart-sdk on the command line.
- if (args != null) {
- int index = args.indexOf('--dart-sdk');
-
- if (index != -1 && (index + 1 < args.length)) {
- return args[index + 1];
- }
-
- for (String arg in args) {
- if (arg.startsWith('--dart-sdk=')) {
- return arg.substring('--dart-sdk='.length);
- }
- }
- }
-
- // Look in env['DART_SDK']
- if (Platform.environment['DART_SDK'] != null) {
- return Platform.environment['DART_SDK']!;
- }
-
- // Use Platform.resolvedExecutable.
- return path.dirname(path.dirname(Platform.resolvedExecutable));
-}
+/// Return the path to the runtime Dart SDK.
+String getSdkPath() => path.dirname(path.dirname(Platform.resolvedExecutable));
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index 58539a7..b63ff5f 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -1852,6 +1852,14 @@
```dart
class C<T> {}
```
+ CONFLICTING_TYPE_VARIABLE_AND_ENUM:
+ sharedName: CONFLICTING_TYPE_VARIABLE_AND_CONTAINER
+ problemMessage: "'{0}' can't be used to name both a type variable and the enum in which the type variable is defined."
+ correctionMessage: Try renaming either the type variable or the enum.
+ hasPublishedDocs: true
+ comment: |-
+ Parameters:
+ 0: the name of the type variable
CONFLICTING_TYPE_VARIABLE_AND_EXTENSION:
sharedName: CONFLICTING_TYPE_VARIABLE_AND_CONTAINER
problemMessage: "'{0}' can't be used to name both a type variable and the extension in which the type variable is defined."
@@ -1911,6 +1919,14 @@
comment: |-
Parameters:
0: the name of the type variable
+ CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM:
+ sharedName: CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+ problemMessage: "'{0}' can't be used to name both a type variable and a member in this enum."
+ correctionMessage: Try renaming either the type variable or the member.
+ hasPublishedDocs: true
+ comment: |-
+ Parameters:
+ 0: the name of the type variable
CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION:
sharedName: CONFLICTING_TYPE_VARIABLE_AND_MEMBER
problemMessage: "'{0}' can't be used to name both a type variable and a member in this extension."
@@ -12216,8 +12232,8 @@
hasPublishedDocs: true
comment: |-
Parameters:
- 0: the name of the enumeration constant that is not defined
- 1: the name of the enumeration used to access the constant
+ 0: the name of the enum constant that is not defined
+ 1: the name of the enum used to access the constant
documentation: |-
#### Description
@@ -19852,7 +19868,7 @@
#### Description
The analyzer produces this diagnostic when a `switch` statement for an enum
- doesn't include an option for one of the values in the enumeration.
+ doesn't include an option for one of the values in the enum.
Note that `null` is always a possible value for an enum and therefore also
must be handled.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 424d0ce..b030e30 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -8,7 +8,6 @@
dependencies:
_fe_analyzer_shared: ^34.0.0
- cli_util: ^0.3.0
collection: ^1.15.0
convert: ^3.0.0
crypto: ^3.0.0
diff --git a/pkg/analyzer/test/src/dart/resolution/class_test.dart b/pkg/analyzer/test/src/dart/resolution/class_test.dart
index fd7aa57..c2ee4c7 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_test.dart
@@ -2,9 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/error/codes.dart';
-import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'context_collection_resolution.dart';
@@ -123,364 +121,6 @@
);
}
- test_error_conflictingConstructorAndStaticField_field() async {
- await assertErrorsInCode(r'''
-class C {
- C.foo();
- static int foo = 0;
-}
-''', [
- error(
- CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD, 14, 3),
- ]);
- }
-
- test_error_conflictingConstructorAndStaticField_getter() async {
- await assertErrorsInCode(r'''
-class C {
- C.foo();
- static int get foo => 0;
-}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER, 14,
- 3),
- ]);
- }
-
- test_error_conflictingConstructorAndStaticField_OK_notSameClass() async {
- await assertNoErrorsInCode(r'''
-class A {
- static int foo = 0;
-}
-class B extends A {
- B.foo();
-}
-''');
- }
-
- test_error_conflictingConstructorAndStaticField_OK_notStatic() async {
- await assertNoErrorsInCode(r'''
-class C {
- C.foo();
- int foo = 0;
-}
-''');
- }
-
- test_error_conflictingConstructorAndStaticField_setter() async {
- await assertErrorsInCode(r'''
-class C {
- C.foo();
- static void set foo(_) {}
-}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER, 14,
- 3),
- ]);
- }
-
- test_error_conflictingConstructorAndStaticMethod() async {
- await assertErrorsInCode(r'''
-class C {
- C.foo();
- static void foo() {}
-}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD, 14,
- 3),
- ]);
- }
-
- test_error_conflictingConstructorAndStaticMethod_OK_notSameClass() async {
- await assertNoErrorsInCode(r'''
-class A {
- static void foo() {}
-}
-class B extends A {
- B.foo();
-}
-''');
- }
-
- test_error_conflictingConstructorAndStaticMethod_OK_notStatic() async {
- await assertNoErrorsInCode(r'''
-class C {
- C.foo();
- void foo() {}
-}
-''');
- }
-
- test_error_conflictingFieldAndMethod_inSuper_field() async {
- await assertErrorsInCode(r'''
-class A {
- foo() {}
-}
-class B extends A {
- int foo = 0;
-}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
- ]);
- }
-
- test_error_conflictingFieldAndMethod_inSuper_getter() async {
- await assertErrorsInCode(r'''
-class A {
- foo() {}
-}
-class B extends A {
- get foo => 0;
-}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
- ]);
- }
-
- test_error_conflictingFieldAndMethod_inSuper_setter() async {
- await assertErrorsInCode(r'''
-class A {
- foo() {}
-}
-class B extends A {
- set foo(_) {}
-}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
- ]);
- }
-
- test_error_conflictingMethodAndField_inSuper_field() async {
- await assertErrorsInCode(r'''
-class A {
- int foo = 0;
-}
-class B extends A {
- foo() {}
-}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 49, 3),
- ]);
- }
-
- test_error_conflictingMethodAndField_inSuper_getter() async {
- await assertErrorsInCode(r'''
-class A {
- get foo => 0;
-}
-class B extends A {
- foo() {}
-}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 50, 3),
- ]);
- }
-
- test_error_conflictingMethodAndField_inSuper_setter() async {
- await assertErrorsInCode(r'''
-class A {
- set foo(_) {}
-}
-class B extends A {
- foo() {}
-}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 50, 3),
- ]);
- }
-
- test_error_duplicateConstructorNamed() async {
- await assertErrorsInCode(r'''
-class C {
- C.foo();
- C.foo();
-}
-''', [
- error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME, 23, 5),
- ]);
- }
-
- test_error_duplicateConstructorNamed_oneIsInvalid() async {
- await assertErrorsInCode(r'''
-class A {}
-class C {
- A.foo();
- C.foo();
-}
-''', [
- error(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 23, 1),
- ]);
- }
-
- test_error_duplicateConstructorUnnamed() async {
- await assertErrorsInCode(r'''
-class C {
- C();
- C();
-}
-''', [
- error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 19, 1),
- ]);
- }
-
- test_error_duplicateConstructorUnnamed_bothNew() async {
- await assertErrorsInCode(r'''
-class C {
- C.new();
- C.new();
-}
-''', [
- error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 23, 5),
- ]);
- }
-
- test_error_duplicateConstructorUnnamed_oneIsInvalid() async {
- await assertErrorsInCode(r'''
-class A {}
-class C {
- A.new();
- C();
-}
-''', [
- error(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 23, 1),
- ]);
- }
-
- test_error_duplicateConstructorUnnamed_oneNew() async {
- await assertErrorsInCode(r'''
-class C {
- C();
- C.new();
-}
-''', [
- error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 19, 5),
- ]);
- }
-
- test_error_extendsNonClass_dynamic() async {
- await assertErrorsInCode(r'''
-class A extends dynamic {}
-''', [
- error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 16, 7),
- ]);
-
- var a = findElement.class_('A');
- assertType(a.supertype, 'Object');
- }
-
- test_error_extendsNonClass_enum() async {
- await assertErrorsInCode(r'''
-enum E { ONE }
-class A extends E {}
-''', [
- error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 31, 1),
- ]);
-
- var a = findElement.class_('A');
- assertType(a.supertype, 'Object');
-
- var eRef = findNode.namedType('E {}');
- assertNamedType(eRef, findElement.enum_('E'), 'E');
- }
-
- test_error_extendsNonClass_mixin() async {
- await assertErrorsInCode(r'''
-mixin M {}
-class A extends M {} // ref
-''', [
- error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
- ]);
-
- var a = findElement.class_('A');
- assertType(a.supertype, 'Object');
-
- var mRef = findNode.namedType('M {} // ref');
- assertNamedType(mRef, findElement.mixin('M'), 'M');
- }
-
- test_error_extendsNonClass_variable() async {
- await assertErrorsInCode(r'''
-int v = 0;
-class A extends v {}
-''', [
- error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
- ]);
-
- var a = findElement.class_('A');
- assertType(a.supertype, 'Object');
- }
-
- test_error_extendsNonClass_variable_generic() async {
- await assertErrorsInCode(r'''
-int v = 0;
-class A extends v<int> {}
-''', [
- error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
- ]);
-
- var a = findElement.class_('A');
- assertType(a.supertype, 'Object');
- }
-
- test_error_memberWithClassName_field() async {
- await assertErrorsInCode(r'''
-class C {
- int C = 42;
-}
-''', [
- error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
- ]);
- }
-
- test_error_memberWithClassName_getter() async {
- await assertErrorsInCode(r'''
-class C {
- int get C => 0;
-}
-''', [
- error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 20, 1),
- ]);
- }
-
- test_error_memberWithClassName_getter_static() async {
- await assertErrorsInCode(r'''
-class C {
- static int get C => 0;
-}
-''', [
- error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 27, 1),
- ]);
-
- var method = findNode.methodDeclaration('C =>');
- expect(method.isGetter, isTrue);
- expect(method.isStatic, isTrue);
- assertElement(method, findElement.getter('C'));
- }
-
- test_error_memberWithClassName_setter() async {
- await assertErrorsInCode(r'''
-class C {
- set C(_) {}
-}
-''', [
- error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
- ]);
- }
-
- test_error_memberWithClassName_setter_static() async {
- await assertErrorsInCode(r'''
-class C {
- static set C(_) {}
-}
-''', [
- error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 23, 1),
- ]);
-
- var method = findNode.methodDeclaration('C(_)');
- expect(method.isSetter, isTrue);
- expect(method.isStatic, isTrue);
- }
-
test_issue32815() async {
await assertErrorsInCode(r'''
class A<T> extends B<T> {}
@@ -503,230 +143,4 @@
error(HintCode.UNUSED_LOCAL_VARIABLE, 150, 1),
]);
}
-
- test_recursiveInterfaceInheritance_extends() async {
- await assertErrorsInCode(r'''
-class A extends B {}
-class B extends A {}
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 27, 1),
- ]);
- }
-
- test_recursiveInterfaceInheritance_extends_implements() async {
- await assertErrorsInCode(r'''
-class A extends B {}
-class B implements A {}
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 27, 1),
- ]);
- }
-
- test_recursiveInterfaceInheritance_implements() async {
- await assertErrorsInCode(r'''
-class A implements B {}
-class B implements A {}
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 30, 1),
- ]);
- }
-
- test_recursiveInterfaceInheritance_mixin() async {
- await assertErrorsInCode(r'''
-class M1 = Object with M2;
-class M2 = Object with M1;
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 2),
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 33, 2),
- ]);
- }
-
- test_recursiveInterfaceInheritance_mixin_superclass() async {
- // Make sure we don't get CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS in
- // addition--that would just be confusing.
- await assertErrorsInCode('''
-class C = D with M;
-class D = C with M;
-class M {}
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 26, 1),
- ]);
- }
-
- test_recursiveInterfaceInheritance_tail() async {
- await assertErrorsInCode(r'''
-abstract class A implements A {}
-class B implements A {}
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 15,
- 1),
- ]);
- }
-
- test_recursiveInterfaceInheritance_tail2() async {
- await assertErrorsInCode(r'''
-abstract class A implements B {}
-abstract class B implements A {}
-class C implements A {}
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 15, 1),
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 48, 1),
- ]);
- }
-
- test_recursiveInterfaceInheritance_tail3() async {
- await assertErrorsInCode(r'''
-abstract class A implements B {}
-abstract class B implements C {}
-abstract class C implements A {}
-class D implements A {}
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 15, 1),
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 48, 1),
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 81, 1),
- ]);
- }
-
- test_recursiveInterfaceInheritanceExtends() async {
- await assertErrorsInCode(r'''
-class A extends A {}
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS, 6, 1),
- ]);
- }
-
- test_recursiveInterfaceInheritanceExtends_abstract() async {
- await assertErrorsInCode(r'''
-class C extends C {
- var bar = 0;
- m();
-}
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS, 6, 1),
- ]);
- }
-
- test_recursiveInterfaceInheritanceImplements() async {
- await assertErrorsInCode('''
-class A implements A {}
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 6,
- 1),
- ]);
- }
-
- test_recursiveInterfaceInheritanceImplements_typeAlias() async {
- await assertErrorsInCode(r'''
-class A {}
-class M {}
-class B = A with M implements B;
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 28,
- 1),
- ]);
- }
-
- test_recursiveInterfaceInheritanceWith() async {
- await assertErrorsInCode(r'''
-class M = Object with M;
-''', [
- error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_WITH, 6, 1),
- ]);
- }
-
- test_undefinedSuperGetter() async {
- await assertErrorsInCode(r'''
-class A {}
-class B extends A {
- get g {
- return super.g;
- }
-}
-''', [
- error(CompileTimeErrorCode.UNDEFINED_SUPER_GETTER, 58, 1),
- ]);
- }
-
- test_undefinedSuperMethod() async {
- await assertErrorsInCode(r'''
-class A {}
-class B extends A {
- m() {
- return super.m();
- }
-}
-''', [
- error(CompileTimeErrorCode.UNDEFINED_SUPER_METHOD, 56, 1),
- ]);
- }
-
- test_undefinedSuperOperator_binaryExpression() async {
- await assertErrorsInCode(r'''
-class A {}
-class B extends A {
- operator +(value) {
- return super + value;
- }
-}
-''', [
- error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 1),
- ]);
- }
-
- test_undefinedSuperOperator_indexBoth() async {
- await assertErrorsInCode(r'''
-class A {}
-class B extends A {
- operator [](index) {
- return super[index]++;
- }
-}
-''', [
- error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 7),
- error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 7),
- ]);
- }
-
- test_undefinedSuperOperator_indexGetter() async {
- await assertErrorsInCode(r'''
-class A {}
-class B extends A {
- operator [](index) {
- return super[index + 1];
- }
-}
-''', [
- error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 11),
- ]);
- }
-
- test_undefinedSuperOperator_indexSetter() async {
- await assertErrorsInCode(r'''
-class A {}
-class B extends A {
- operator []=(index, value) {
- super[index] = 0;
- }
-}
-''', [
- error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 71, 7),
- ]);
- }
-
- test_undefinedSuperSetter() async {
- await assertErrorsInCode(r'''
-class A {}
-class B extends A {
- f() {
- super.m = 0;
- }
-}
-''', [
- error(CompileTimeErrorCode.UNDEFINED_SUPER_SETTER, 49, 1),
- ]);
- }
}
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_field_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_field_test.dart
new file mode 100644
index 0000000..6cb825d
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_field_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConflictingConstructorAndStaticFieldTest);
+ });
+}
+
+@reflectiveTest
+class ConflictingConstructorAndStaticFieldTest
+ extends PubPackageResolutionTest {
+ test_class_field() async {
+ await assertErrorsInCode(r'''
+class C {
+ C.foo();
+ static int foo = 0;
+}
+''', [
+ error(
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD, 14, 3),
+ ]);
+ }
+
+ test_class_getter() async {
+ await assertErrorsInCode(r'''
+class C {
+ C.foo();
+ static int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER, 14,
+ 3),
+ ]);
+ }
+
+ test_class_OK_notSameClass() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ static int foo = 0;
+}
+class B extends A {
+ B.foo();
+}
+''');
+ }
+
+ test_class_OK_notStatic() async {
+ await assertNoErrorsInCode(r'''
+class C {
+ C.foo();
+ int foo = 0;
+}
+''');
+ }
+
+ test_class_setter() async {
+ await assertErrorsInCode(r'''
+class C {
+ C.foo();
+ static void set foo(_) {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER, 14,
+ 3),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_method_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_method_test.dart
new file mode 100644
index 0000000..a880ff5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_method_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConflictingConstructorAndStaticMethodTest);
+ });
+}
+
+@reflectiveTest
+class ConflictingConstructorAndStaticMethodTest
+ extends PubPackageResolutionTest {
+ test_class_OK_notSameClass() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ static void foo() {}
+}
+class B extends A {
+ B.foo();
+}
+''');
+ }
+
+ test_class_OK_notStatic() async {
+ await assertNoErrorsInCode(r'''
+class C {
+ C.foo();
+ void foo() {}
+}
+''');
+ }
+
+ test_error_conflictingConstructorAndStaticMethod() async {
+ await assertErrorsInCode(r'''
+class C {
+ C.foo();
+ static void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD, 14,
+ 3),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_field_and_method_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_field_and_method_test.dart
new file mode 100644
index 0000000..2abf55f
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_field_and_method_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConflictingFieldAndMethodTest);
+ });
+}
+
+@reflectiveTest
+class ConflictingFieldAndMethodTest extends PubPackageResolutionTest {
+ test_class_inSuper_field() async {
+ await assertErrorsInCode(r'''
+class A {
+ foo() {}
+}
+class B extends A {
+ int foo = 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
+ ]);
+ }
+
+ test_class_inSuper_getter() async {
+ await assertErrorsInCode(r'''
+class A {
+ foo() {}
+}
+class B extends A {
+ get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
+ ]);
+ }
+
+ test_class_inSuper_setter() async {
+ await assertErrorsInCode(r'''
+class A {
+ foo() {}
+}
+class B extends A {
+ set foo(_) {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_method_and_field_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_method_and_field_test.dart
new file mode 100644
index 0000000..1366e18
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_method_and_field_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConflictingMethodAndFieldTest);
+ });
+}
+
+@reflectiveTest
+class ConflictingMethodAndFieldTest extends PubPackageResolutionTest {
+ test_class_inSuper_field() async {
+ await assertErrorsInCode(r'''
+class A {
+ int foo = 0;
+}
+class B extends A {
+ foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 49, 3),
+ ]);
+ }
+
+ test_class_inSuper_getter() async {
+ await assertErrorsInCode(r'''
+class A {
+ get foo => 0;
+}
+class B extends A {
+ foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 50, 3),
+ ]);
+ }
+
+ test_class_inSuper_setter() async {
+ await assertErrorsInCode(r'''
+class A {
+ set foo(_) {}
+}
+class B extends A {
+ foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 50, 3),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart
index 85205db..cd47d2e 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart
@@ -451,7 +451,7 @@
@reflectiveTest
class ConflictingStaticAndInstanceEnumTest extends PubPackageResolutionTest {
- test_hashCode() async {
+ test_constant_hashCode() async {
await assertErrorsInCode(r'''
enum E {
a, hashCode, b
@@ -461,7 +461,7 @@
]);
}
- test_index() async {
+ test_constant_index() async {
await assertErrorsInCode(r'''
enum E {
a, index, b
@@ -471,7 +471,7 @@
]);
}
- test_noSuchMethod() async {
+ test_constant_noSuchMethod() async {
await assertErrorsInCode(r'''
enum E {
a, noSuchMethod, b
@@ -481,7 +481,7 @@
]);
}
- test_runtimeType() async {
+ test_constant_runtimeType() async {
await assertErrorsInCode(r'''
enum E {
a, runtimeType, b
@@ -491,7 +491,7 @@
]);
}
- test_toString() async {
+ test_constant_toString() async {
await assertErrorsInCode(r'''
enum E {
a, toString, b
@@ -500,6 +500,214 @@
error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 14, 8),
]);
}
+
+ test_field_dartCoreEnum() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static final int hashCode = 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 33, 8),
+ ]);
+ }
+
+ test_field_mixin_getter() async {
+ await assertErrorsInCode(r'''
+mixin M {
+ int get foo => 0;
+}
+
+enum E with M {
+ v;
+ static final int foo = 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 73, 3),
+ ]);
+ }
+
+ test_field_mixin_method() async {
+ await assertErrorsInCode(r'''
+mixin M {
+ void foo() {}
+}
+
+enum E with M {
+ v;
+ static final int foo = 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 69, 3),
+ ]);
+ }
+
+ test_field_mixin_setter() async {
+ await assertErrorsInCode(r'''
+mixin M {
+ set foo(int _) {}
+}
+
+enum E with M {
+ v;
+ static final int foo = 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 73, 3),
+ ]);
+ }
+
+ test_field_this_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static final int foo = 0;
+ int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 33, 3),
+ ]);
+ }
+
+ test_field_this_method() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static final int foo = 0;
+ void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 33, 3),
+ ]);
+ }
+
+ test_field_this_setter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static final int foo = 0;
+ set foo(int _) {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 33, 3),
+ ]);
+ }
+
+ test_getter_this_setter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static int get foo => 0;
+ set foo(_) {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 31, 3),
+ ]);
+ }
+
+ test_method_dartCoreEnum() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static int hashCode() => 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 27, 8),
+ ]);
+ }
+
+ test_method_mixin_getter() async {
+ await assertErrorsInCode(r'''
+mixin M {
+ int get foo => 0;
+}
+
+enum E with M {
+ v;
+ static void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 68, 3),
+ ]);
+ }
+
+ test_method_mixin_method() async {
+ await assertErrorsInCode(r'''
+mixin M {
+ void foo() {}
+}
+
+enum E with M {
+ v;
+ static void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 64, 3),
+ ]);
+ }
+
+ test_method_mixin_setter() async {
+ await assertErrorsInCode(r'''
+mixin M {
+ set foo(int _) {}
+}
+
+enum E with M {
+ v;
+ static void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 68, 3),
+ ]);
+ }
+
+ test_method_this_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static void foo() {}
+ int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 28, 3),
+ ]);
+ }
+
+ test_method_this_method() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static void foo() {}
+ void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 28, 3),
+ ]);
+ }
+
+ test_method_this_setter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static void foo() {}
+ set foo(int _) {}
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 28, 3),
+ ]);
+ }
+
+ test_setter_this_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static set foo(_) {}
+ int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 27, 3),
+ ]);
+ }
}
@reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_container_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_container_test.dart
index ecf579a..14f3ce5 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_container_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_container_test.dart
@@ -10,6 +10,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ConflictingTypeVariableAndClassTest);
+ defineReflectiveTests(ConflictingTypeVariableAndEnumTest);
defineReflectiveTests(ConflictingTypeVariableAndExtensionTest);
defineReflectiveTests(ConflictingTypeVariableAndMixinTest);
});
@@ -27,6 +28,19 @@
}
@reflectiveTest
+class ConflictingTypeVariableAndEnumTest extends PubPackageResolutionTest {
+ test_conflict() async {
+ await assertErrorsInCode(r'''
+enum E<E> {
+ v
+}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_ENUM, 7, 1),
+ ]);
+ }
+}
+
+@reflectiveTest
class ConflictingTypeVariableAndExtensionTest extends PubPackageResolutionTest {
test_conflict() async {
await assertErrorsInCode(r'''
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart
index efab14b..00ce562 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart
@@ -10,6 +10,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ConflictingTypeVariableAndMemberClassTest);
+ defineReflectiveTests(ConflictingTypeVariableAndMemberEnumTest);
defineReflectiveTests(ConflictingTypeVariableAndMemberExtensionTest);
defineReflectiveTests(ConflictingTypeVariableAndMemberMixinTest);
});
@@ -86,6 +87,46 @@
}
@reflectiveTest
+class ConflictingTypeVariableAndMemberEnumTest
+ extends PubPackageResolutionTest {
+ test_getter() async {
+ await assertErrorsInCode(r'''
+enum A<T> {
+ v;
+ get T => null;
+}
+''', [
+ error(
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM, 7, 1),
+ ]);
+ }
+
+ test_method() async {
+ await assertErrorsInCode(r'''
+enum A<T> {
+ v;
+ void T() {}
+}
+''', [
+ error(
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM, 7, 1),
+ ]);
+ }
+
+ test_setter() async {
+ await assertErrorsInCode(r'''
+enum A<T> {
+ v;
+ set T(x) {}
+}
+''', [
+ error(
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM, 7, 1),
+ ]);
+ }
+}
+
+@reflectiveTest
class ConflictingTypeVariableAndMemberExtensionTest
extends PubPackageResolutionTest {
test_getter() async {
diff --git a/pkg/analyzer/test/src/diagnostics/const_not_initialized_test.dart b/pkg/analyzer/test/src/diagnostics/const_not_initialized_test.dart
index 85b1174..3fe5d0c 100644
--- a/pkg/analyzer/test/src/diagnostics/const_not_initialized_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_not_initialized_test.dart
@@ -16,19 +16,21 @@
@reflectiveTest
class ConstNotInitializedTest extends PubPackageResolutionTest
- with ConstNotInitializedTestCases {}
-
-mixin ConstNotInitializedTestCases on PubPackageResolutionTest {
- test_extension_static() async {
+ with ConstNotInitializedTestCases {
+ test_enum_static() async {
await assertErrorsInCode('''
-extension E on String {
+enum E {
+ v;
static const F;
-}''', [
- error(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 39, 1),
+}
+''', [
+ error(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 29, 1),
]);
}
+}
- test_instanceField_static() async {
+mixin ConstNotInitializedTestCases on PubPackageResolutionTest {
+ test_class_static() async {
await assertErrorsInCode(r'''
class A {
static const F;
@@ -38,6 +40,16 @@
]);
}
+ test_extension_static() async {
+ await assertErrorsInCode('''
+extension E on String {
+ static const F;
+}
+''', [
+ error(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 39, 1),
+ ]);
+ }
+
test_local() async {
await assertErrorsInCode(r'''
f() {
@@ -49,7 +61,7 @@
]);
}
- test_top_level() async {
+ test_topLevel() async {
await assertErrorsInCode('''
const F;
''', [
diff --git a/pkg/analyzer/test/src/diagnostics/duplicate_constructor_default_test.dart b/pkg/analyzer/test/src/diagnostics/duplicate_constructor_default_test.dart
new file mode 100644
index 0000000..d0d1172
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/duplicate_constructor_default_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(DuplicateConstructorDefaultTest);
+ });
+}
+
+@reflectiveTest
+class DuplicateConstructorDefaultTest extends PubPackageResolutionTest {
+ test_class_empty_empty() async {
+ await assertErrorsInCode(r'''
+class C {
+ C();
+ C();
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 19, 1),
+ ]);
+ }
+
+ test_class_empty_new() async {
+ await assertErrorsInCode(r'''
+class C {
+ C();
+ C.new();
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 19, 5),
+ ]);
+ }
+
+ test_class_new_new() async {
+ await assertErrorsInCode(r'''
+class C {
+ C.new();
+ C.new();
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 23, 5),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/duplicate_constructor_name_test.dart b/pkg/analyzer/test/src/diagnostics/duplicate_constructor_name_test.dart
new file mode 100644
index 0000000..b99fc99
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/duplicate_constructor_name_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(DuplicateConstructorNameTest);
+ });
+}
+
+@reflectiveTest
+class DuplicateConstructorNameTest extends PubPackageResolutionTest {
+ test_class() async {
+ await assertErrorsInCode(r'''
+class C {
+ C.foo();
+ C.foo();
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME, 23, 5),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart b/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
index 66df7dcab..09a546f 100644
--- a/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
@@ -13,6 +13,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(DuplicateDefinitionTest);
defineReflectiveTests(DuplicateDefinitionClassTest);
+ defineReflectiveTests(DuplicateDefinitionEnumTest);
defineReflectiveTests(DuplicateDefinitionExtensionTest);
defineReflectiveTests(DuplicateDefinitionMixinTest);
});
@@ -327,6 +328,333 @@
}
@reflectiveTest
+class DuplicateDefinitionEnumTest extends PubPackageResolutionTest {
+ test_instance_field_field() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ final int foo = 0;
+ final int foo = 0;
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 47, 3),
+ ]);
+ }
+
+ test_instance_field_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ final int foo = 0;
+ int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 45, 3),
+ ]);
+ }
+
+ test_instance_field_method() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ final int foo = 0;
+ void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 42, 3),
+ ]);
+ }
+
+ test_instance_fieldFinal_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ final int foo = 0;
+ int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 45, 3),
+ ]);
+ }
+
+ test_instance_fieldFinal_setter() async {
+ await assertNoErrorsInCode(r'''
+enum E {
+ v;
+ final int foo = 0;
+ set foo(int x) {}
+}
+''');
+ }
+
+ test_instance_getter_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ int get foo => 0;
+ int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 44, 3),
+ ]);
+ }
+
+ test_instance_getter_method() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ int get foo => 0;
+ void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 41, 3),
+ ]);
+ }
+
+ test_instance_getter_setter() async {
+ await assertNoErrorsInCode(r'''
+enum E {
+ v;
+ int get foo => 0;
+ set foo(_) {}
+}
+''');
+ }
+
+ test_instance_method_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ void foo() {}
+ int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 40, 3),
+ ]);
+ }
+
+ test_instance_method_method() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ void foo() {}
+ void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 37, 3),
+ ]);
+ }
+
+ test_instance_method_setter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ void foo() {}
+ set foo(_) {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 36, 3),
+ ]);
+ }
+
+ test_instance_setter_getter() async {
+ await assertNoErrorsInCode(r'''
+enum E {
+ v;
+ set foo(_) {}
+ int get foo => 0;
+}
+''');
+ }
+
+ test_instance_setter_method() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ set foo(_) {}
+ void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 37, 3),
+ ]);
+ }
+
+ test_instance_setter_setter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ void set foo(_) {}
+ void set foo(_) {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 46, 3),
+ ]);
+ }
+
+ test_static_field_field() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static int foo = 0;
+ static int foo = 0;
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 49, 3),
+ ]);
+ }
+
+ test_static_field_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static int foo = 0;
+ static int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 53, 3),
+ ]);
+ }
+
+ test_static_field_method() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static int foo = 0;
+ static void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 50, 3),
+ ]);
+ }
+
+ test_static_fieldFinal_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static final int foo = 0;
+ static int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 59, 3),
+ ]);
+ }
+
+ test_static_fieldFinal_setter() async {
+ await assertNoErrorsInCode(r'''
+enum E {
+ v;
+ static final int foo = 0;
+ static set foo(int x) {}
+}
+''');
+ }
+
+ test_static_getter_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static int get foo => 0;
+ static int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 58, 3),
+ ]);
+ }
+
+ test_static_getter_method() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static int get foo => 0;
+ static void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 55, 3),
+ ]);
+ }
+
+ test_static_getter_setter() async {
+ await assertNoErrorsInCode(r'''
+enum E {
+ v;
+ static int get foo => 0;
+ static set foo(_) {}
+}
+''');
+ }
+
+ test_static_method_getter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static void foo() {}
+ static int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 54, 3),
+ ]);
+ }
+
+ test_static_method_method() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static void foo() {}
+ static void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 51, 3),
+ ]);
+ }
+
+ test_static_method_setter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static void foo() {}
+ static set foo(_) {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 50, 3),
+ ]);
+ }
+
+ test_static_setter_getter() async {
+ await assertNoErrorsInCode(r'''
+enum E {
+ v;
+ static set foo(_) {}
+ static int get foo => 0;
+}
+''');
+ }
+
+ test_static_setter_method() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static set foo(_) {}
+ static void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 51, 3),
+ ]);
+ }
+
+ test_static_setter_setter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ static void set foo(_) {}
+ static void set foo(_) {}
+}
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 60, 3),
+ ]);
+ }
+}
+
+@reflectiveTest
class DuplicateDefinitionExtensionTest extends PubPackageResolutionTest {
test_extendedType_instance() async {
await assertNoErrorsInCode('''
diff --git a/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart b/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
index ab697b0..e38a3bb 100644
--- a/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
@@ -15,6 +15,71 @@
@reflectiveTest
class ExtendsNonClassTest extends PubPackageResolutionTest {
+ test_class_dynamic() async {
+ await assertErrorsInCode(r'''
+class A extends dynamic {}
+''', [
+ error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 16, 7),
+ ]);
+
+ var a = findElement.class_('A');
+ assertType(a.supertype, 'Object');
+ }
+
+ test_class_enum() async {
+ await assertErrorsInCode(r'''
+enum E { ONE }
+class A extends E {}
+''', [
+ error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 31, 1),
+ ]);
+
+ var a = findElement.class_('A');
+ assertType(a.supertype, 'Object');
+
+ var eRef = findNode.namedType('E {}');
+ assertNamedType(eRef, findElement.enum_('E'), 'E');
+ }
+
+ test_class_mixin() async {
+ await assertErrorsInCode(r'''
+mixin M {}
+class A extends M {} // ref
+''', [
+ error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
+ ]);
+
+ var a = findElement.class_('A');
+ assertType(a.supertype, 'Object');
+
+ var mRef = findNode.namedType('M {} // ref');
+ assertNamedType(mRef, findElement.mixin('M'), 'M');
+ }
+
+ test_class_variable() async {
+ await assertErrorsInCode(r'''
+int v = 0;
+class A extends v {}
+''', [
+ error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
+ ]);
+
+ var a = findElement.class_('A');
+ assertType(a.supertype, 'Object');
+ }
+
+ test_class_variable_generic() async {
+ await assertErrorsInCode(r'''
+int v = 0;
+class A extends v<int> {}
+''', [
+ error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
+ ]);
+
+ var a = findElement.class_('A');
+ assertType(a.supertype, 'Object');
+ }
+
test_Never() async {
await assertErrorsInCode('''
class A extends Never {}
diff --git a/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart b/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
index e4fb280..d5bb2f6 100644
--- a/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
@@ -92,7 +92,7 @@
@reflectiveTest
class FinalNotInitializedWithNullSafetyTest extends PubPackageResolutionTest {
- test_field_abstract() async {
+ test_class_field_abstract() async {
await assertNoErrorsInCode('''
abstract class A {
abstract final int x;
@@ -100,7 +100,7 @@
''');
}
- test_field_abstract_with_constructor() async {
+ test_class_field_abstract_with_constructor() async {
await assertNoErrorsInCode('''
abstract class A {
abstract final int x;
@@ -109,7 +109,7 @@
''');
}
- test_field_external() async {
+ test_class_field_external() async {
await assertNoErrorsInCode('''
class A {
external final int x;
@@ -117,7 +117,15 @@
''');
}
- test_field_external_with_constructor() async {
+ test_class_field_external_static() async {
+ await assertNoErrorsInCode('''
+class A {
+ external static final int x;
+}
+''');
+ }
+
+ test_class_field_external_with_constructor() async {
await assertNoErrorsInCode('''
class A {
external final int x;
@@ -126,15 +134,7 @@
''');
}
- test_field_noConstructor_initializer() async {
- await assertNoErrorsInCode('''
-class C {
- late final f = 1;
-}
-''');
- }
-
- test_field_noConstructor_noInitializer() async {
+ test_class_field_late_noConstructor_noInitializer() async {
await assertNoErrorsInCode('''
class C {
late final f;
@@ -142,7 +142,24 @@
''');
}
- test_field_ofClass() async {
+ test_class_field_late_unnamedConstructor_noInitializer() async {
+ await assertNoErrorsInCode('''
+class C {
+ late final f;
+ C();
+}
+''');
+ }
+
+ test_class_field_noConstructor_initializer() async {
+ await assertNoErrorsInCode('''
+class C {
+ final f = 1;
+}
+''');
+ }
+
+ test_class_field_noConstructor_noInitializer() async {
await assertErrorsInCode('''
abstract class A {
final int x;
@@ -152,42 +169,73 @@
]);
}
- test_field_unnamedConstructor_constructorInitializer() async {
+ test_class_field_unnamedConstructor_constructorInitializer() async {
await assertNoErrorsInCode('''
class C {
- late final f;
+ final f;
C() : f = 2;
}
''');
}
- test_field_unnamedConstructor_fieldFormalParameter() async {
+ test_class_field_unnamedConstructor_fieldFormalParameter() async {
await assertNoErrorsInCode('''
class C {
- late final f;
+ final f;
C(this.f);
}
''');
}
- test_field_unnamedConstructor_initializer() async {
+ test_class_field_unnamedConstructor_initializer() async {
await assertNoErrorsInCode('''
class C {
- late final f = 1;
+ final f = 1;
C();
}
''');
}
- test_field_unnamedConstructor_noInitializer() async {
+ test_enum_field_constructorFieldInitializer() async {
await assertNoErrorsInCode('''
-class C {
- late final f;
- C();
+enum E {
+ v;
+ final int x;
+ const E() : x = 0;
}
''');
}
+ test_enum_field_fieldFormalParameter() async {
+ await assertNoErrorsInCode('''
+enum E {
+ v(0);
+ final int x;
+ const E(this.x);
+}
+''');
+ }
+
+ test_enum_field_hasInitializer() async {
+ await assertNoErrorsInCode('''
+enum E {
+ v;
+ final int x = 0;
+}
+''');
+ }
+
+ test_enum_field_noConstructor_noInitializer() async {
+ await assertErrorsInCode('''
+enum E {
+ v;
+ final int x;
+}
+''', [
+ error(CompileTimeErrorCode.FINAL_NOT_INITIALIZED, 26, 1),
+ ]);
+ }
+
test_localVariable_initializer() async {
await assertErrorsInCode('''
f() {
@@ -208,15 +256,7 @@
]);
}
- test_static_field_external() async {
- await assertNoErrorsInCode('''
-class A {
- external static final int x;
-}
-''');
- }
-
- test_variable_external() async {
+ test_topLevel_external() async {
await assertNoErrorsInCode('''
external final int x;
''');
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_constructor_name_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_constructor_name_test.dart
index 049f378..d6692a3 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_constructor_name_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_constructor_name_test.dart
@@ -26,6 +26,31 @@
]);
}
+ test_notEnclosingClassName_named() async {
+ await assertErrorsInCode(r'''
+class A {}
+class B {
+ A.foo();
+ B.foo();
+}
+''', [
+ error(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 23, 1),
+ ]);
+ }
+
+ test_notEnclosingClassName_new() async {
+ await assertErrorsInCode(r'''
+class A {}
+
+class B {
+ A.new();
+ B();
+}
+''', [
+ error(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 24, 1),
+ ]);
+ }
+
test_notEnclosingClassName_undefined() async {
await assertErrorsInCode(r'''
class A {
diff --git a/pkg/analyzer/test/src/diagnostics/late_final_field_with_const_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/late_final_field_with_const_constructor_test.dart
index 688771e..47b76c5 100644
--- a/pkg/analyzer/test/src/diagnostics/late_final_field_with_const_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/late_final_field_with_const_constructor_test.dart
@@ -87,7 +87,27 @@
''');
}
- test_inExtension() async {
+ test_enum_instance_hasInitializer() async {
+ await assertErrorsInCode('''
+enum E {
+ v;
+ late final f = 0;
+}
+''', [
+ error(_errorCode, 16, 4),
+ ]);
+ }
+
+ test_enum_static() async {
+ await assertNoErrorsInCode('''
+enum E {
+ v;
+ static late final f = 0;
+}
+''');
+ }
+
+ test_extension() async {
// https://github.com/dart-lang/sdk/issues/46952
// This test is here because the code that tests for
// LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR is where the referenced issue was
diff --git a/pkg/analyzer/test/src/diagnostics/member_with_class_name_test.dart b/pkg/analyzer/test/src/diagnostics/member_with_class_name_test.dart
index d9583c5..9057423 100644
--- a/pkg/analyzer/test/src/diagnostics/member_with_class_name_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/member_with_class_name_test.dart
@@ -45,11 +45,41 @@
]);
}
+ test_class_getter_static() async {
+ await assertErrorsInCode(r'''
+class A {
+ static int get A => 0;
+}
+''', [
+ error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 27, 1),
+ ]);
+ }
+
test_class_method() async {
// No test because a method named the same as the enclosing class is
// indistinguishable from a constructor.
}
+ test_class_setter() async {
+ await assertErrorsInCode(r'''
+class A {
+ set A(_) {}
+}
+''', [
+ error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
+ ]);
+ }
+
+ test_class_setter_static() async {
+ await assertErrorsInCode(r'''
+class A {
+ static set A(_) {}
+}
+''', [
+ error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 23, 1),
+ ]);
+ }
+
test_mixin_getter() async {
await assertErrorsInCode(r'''
mixin M {
diff --git a/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_extends_test.dart b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_extends_test.dart
new file mode 100644
index 0000000..a3123c8
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_extends_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(RecursiveInterfaceInheritanceExtendsTest);
+ });
+}
+
+@reflectiveTest
+class RecursiveInterfaceInheritanceExtendsTest
+ extends PubPackageResolutionTest {
+ test_class() async {
+ await assertErrorsInCode(r'''
+class A extends A {}
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS, 6, 1),
+ ]);
+ }
+
+ test_class_abstract() async {
+ await assertErrorsInCode(r'''
+class C extends C {
+ var foo = 0;
+ bar();
+}
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS, 6, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_implements_test.dart b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_implements_test.dart
new file mode 100644
index 0000000..aaf824b
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_implements_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(RecursiveInterfaceInheritanceImplementsTest);
+ });
+}
+
+@reflectiveTest
+class RecursiveInterfaceInheritanceImplementsTest
+ extends PubPackageResolutionTest {
+ test_class() async {
+ await assertErrorsInCode('''
+class A implements A {}
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 6,
+ 1),
+ ]);
+ }
+
+ test_class_tail() async {
+ await assertErrorsInCode(r'''
+abstract class A implements A {}
+class B implements A {}
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 15,
+ 1),
+ ]);
+ }
+
+ test_classTypeAlias() async {
+ await assertErrorsInCode(r'''
+class A {}
+class M {}
+class B = A with M implements B;
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 28,
+ 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_test.dart b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_test.dart
index 472f7914..eee8fc5 100644
--- a/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_test.dart
@@ -15,7 +15,27 @@
@reflectiveTest
class RecursiveInterfaceInheritanceTest extends PubPackageResolutionTest {
- test_loop() async {
+ test_class_extends() async {
+ await assertErrorsInCode(r'''
+class A extends B {}
+class B extends A {}
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 27, 1),
+ ]);
+ }
+
+ test_class_extends_implements() async {
+ await assertErrorsInCode(r'''
+class A extends B {}
+class B implements A {}
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 27, 1),
+ ]);
+ }
+
+ test_class_implements() async {
await assertErrorsInCode('''
class A implements B {}
class B implements A {}
@@ -25,7 +45,7 @@
]);
}
- test_loop_generic() async {
+ test_class_implements_generic() async {
await assertErrorsInCode('''
class A<T> implements B<T> {}
class B<T> implements A<T> {}
@@ -35,7 +55,7 @@
]);
}
- test_loop_generic_typeArgument() async {
+ test_class_implements_generic_typeArgument() async {
await assertErrorsInCode('''
class A<T> implements B<List<T>> {}
class B<T> implements A<List<T>> {}
@@ -44,4 +64,51 @@
error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 42, 1),
]);
}
+
+ test_class_implements_tail2() async {
+ await assertErrorsInCode(r'''
+abstract class A implements B {}
+abstract class B implements A {}
+class C implements A {}
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 15, 1),
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 48, 1),
+ ]);
+ }
+
+ test_class_implements_tail3() async {
+ await assertErrorsInCode(r'''
+abstract class A implements B {}
+abstract class B implements C {}
+abstract class C implements A {}
+class D implements A {}
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 15, 1),
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 48, 1),
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 81, 1),
+ ]);
+ }
+
+ test_classTypeAlias_mixin() async {
+ await assertErrorsInCode(r'''
+class M1 = Object with M2;
+class M2 = Object with M1;
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 2),
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 33, 2),
+ ]);
+ }
+
+ test_classTypeAlias_mixin_superclass() async {
+ // Make sure we don't get CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS in
+ // addition--that would just be confusing.
+ await assertErrorsInCode('''
+class C = D with M;
+class D = C with M;
+class M {}
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 26, 1),
+ ]);
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_with_test.dart b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_with_test.dart
new file mode 100644
index 0000000..b9130d5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_with_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(RecursiveInterfaceInheritanceWithTest);
+ });
+}
+
+@reflectiveTest
+class RecursiveInterfaceInheritanceWithTest extends PubPackageResolutionTest {
+ test_classTypeAlias() async {
+ await assertErrorsInCode(r'''
+class M = Object with M;
+''', [
+ error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_WITH, 6, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 5ca7e69..3c0d14a 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -64,8 +64,14 @@
as class_instantiation_access_to_member;
import 'concrete_class_with_abstract_member_test.dart'
as concrete_class_with_abstract_member;
+import 'conflicting_constructor_and_static_field_test.dart'
+ as conflicting_constructor_and_static_field;
+import 'conflicting_constructor_and_static_method_test.dart'
+ as conflicting_constructor_and_static_method;
+import 'conflicting_field_and_method_test.dart' as conflicting_field_and_method;
import 'conflicting_generic_interfaces_test.dart'
as conflicting_generic_interfaces;
+import 'conflicting_method_and_field_test.dart' as conflicting_method_and_field;
import 'conflicting_static_and_instance_test.dart'
as conflicting_static_and_instance;
import 'conflicting_type_variable_and_container_test.dart'
@@ -136,6 +142,9 @@
import 'deprecated_member_use_test.dart' as deprecated_member_use;
import 'deprecated_mixin_function_test.dart' as deprecated_mixin_function;
import 'division_optimization_test.dart' as division_optimization;
+import 'duplicate_constructor_default_test.dart'
+ as duplicate_constructor_default;
+import 'duplicate_constructor_name_test.dart' as duplicate_constructor_name;
import 'duplicate_definition_test.dart' as duplicate_definition;
import 'duplicate_field_formal_parameter_test.dart'
as duplicate_field_formal_parameter;
@@ -583,8 +592,14 @@
import 'recursive_constructor_redirect_test.dart'
as recursive_constructor_redirect;
import 'recursive_factory_redirect_test.dart' as recursive_factory_redirect;
+import 'recursive_interface_inheritance_extends_test.dart'
+ as recursive_interface_inheritance_extends;
+import 'recursive_interface_inheritance_implements_test.dart'
+ as recursive_interface_inheritance_implements;
import 'recursive_interface_inheritance_test.dart'
as recursive_interface_inheritance;
+import 'recursive_interface_inheritance_with_test.dart'
+ as recursive_interface_inheritance_with;
import 'redirect_generative_to_missing_constructor_test.dart'
as redirect_generative_to_missing_constructor;
import 'redirect_generative_to_non_generative_constructor_test.dart'
@@ -710,7 +725,10 @@
as undefined_referenced_parameter;
import 'undefined_setter_test.dart' as undefined_setter;
import 'undefined_shown_name_test.dart' as undefined_shown_name;
+import 'undefined_super_getter_test.dart' as undefined_super_getter;
import 'undefined_super_method_test.dart' as undefined_super_method;
+import 'undefined_super_operator_test.dart' as undefined_super_operator;
+import 'undefined_super_setter_test.dart' as undefined_super_setter;
import 'unignorable_ignore_test.dart' as unignorable_ignore;
import 'unnecessary_cast_test.dart' as unnecessary_cast;
import 'unnecessary_ignore_test.dart' as unnecessary_ignore;
@@ -800,7 +818,11 @@
cast_to_non_type.main();
class_instantiation_access_to_member.main();
concrete_class_with_abstract_member.main();
+ conflicting_constructor_and_static_field.main();
+ conflicting_constructor_and_static_method.main();
+ conflicting_field_and_method.main();
conflicting_generic_interfaces.main();
+ conflicting_method_and_field.main();
conflicting_static_and_instance.main();
conflicting_type_variable_and_container.main();
conflicting_type_variable_and_member.main();
@@ -847,6 +869,8 @@
deprecated_member_use.main();
deprecated_mixin_function.main();
division_optimization.main();
+ duplicate_constructor_default.main();
+ duplicate_constructor_name.main();
duplicate_definition.main();
duplicate_field_formal_parameter.main();
duplicate_hidden_name.main();
@@ -1139,7 +1163,10 @@
recursive_compile_time_constant.main();
recursive_constructor_redirect.main();
recursive_factory_redirect.main();
+ recursive_interface_inheritance_extends.main();
+ recursive_interface_inheritance_implements.main();
recursive_interface_inheritance.main();
+ recursive_interface_inheritance_with.main();
redirect_generative_to_missing_constructor.main();
redirect_generative_to_non_generative_constructor.main();
redirect_to_abstract_class_constructor.main();
@@ -1226,7 +1253,10 @@
undefined_referenced_parameter.main();
undefined_setter.main();
undefined_shown_name.main();
+ undefined_super_getter.main();
undefined_super_method.main();
+ undefined_super_operator.main();
+ undefined_super_setter.main();
unignorable_ignore.main();
unnecessary_import.main();
unnecessary_cast.main();
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_super_getter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_super_getter_test.dart
new file mode 100644
index 0000000..d932f3e
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_super_getter_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UndefinedSuperGetterTest);
+ });
+}
+
+@reflectiveTest
+class UndefinedSuperGetterTest extends PubPackageResolutionTest {
+ test_class() async {
+ await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+ get g {
+ return super.g;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_SUPER_GETTER, 58, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_super_method_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_super_method_test.dart
index 0c1192c..8c77143 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_super_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_super_method_test.dart
@@ -15,20 +15,39 @@
@reflectiveTest
class UndefinedSuperMethodTest extends PubPackageResolutionTest {
- test_error_undefinedSuperMethod() async {
+ test_class() async {
+ await assertErrorsInCode(r'''
+class A {}
+
+class B extends A {
+ void bar() {
+ super.foo();
+ }
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_SUPER_METHOD, 57, 3),
+ ]);
+
+ var invocation = findNode.methodInvocation('foo()');
+ assertElementNull(invocation.methodName);
+ assertInvokeTypeDynamic(invocation);
+ assertTypeDynamic(invocation);
+ }
+
+ test_mixin() async {
await assertErrorsInCode(r'''
class A {}
mixin M on A {
void bar() {
- super.foo(42);
+ super.foo();
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_SUPER_METHOD, 52, 3),
]);
- var invocation = findNode.methodInvocation('foo(42)');
+ var invocation = findNode.methodInvocation('foo()');
assertElementNull(invocation.methodName);
assertInvokeTypeDynamic(invocation);
assertTypeDynamic(invocation);
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_super_operator_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_super_operator_test.dart
new file mode 100644
index 0000000..623f271
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_super_operator_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UndefinedSuperOperatorTest);
+ });
+}
+
+@reflectiveTest
+class UndefinedSuperOperatorTest extends PubPackageResolutionTest {
+ test_class_binaryExpression() async {
+ await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+ operator +(value) {
+ return super + value;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 1),
+ ]);
+ }
+
+ test_class_indexBoth() async {
+ await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+ operator [](index) {
+ return super[index]++;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 7),
+ error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 7),
+ ]);
+ }
+
+ test_class_indexGetter() async {
+ await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+ operator [](index) {
+ return super[index + 1];
+ }
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 11),
+ ]);
+ }
+
+ test_class_indexSetter() async {
+ await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+ operator []=(index, value) {
+ super[index] = 0;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 71, 7),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_super_setter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_super_setter_test.dart
new file mode 100644
index 0000000..934fbd5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_super_setter_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UndefinedSuperSetterTest);
+ });
+}
+
+@reflectiveTest
+class UndefinedSuperSetterTest extends PubPackageResolutionTest {
+ test_class() async {
+ await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+ f() {
+ super.m = 0;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_SUPER_SETTER, 49, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/lint/pub_test.dart b/pkg/analyzer/test/src/lint/pub_test.dart
index b5fbe2a..aa4dfe1 100644
--- a/pkg/analyzer/test/src/lint/pub_test.dart
+++ b/pkg/analyzer/test/src/lint/pub_test.dart
@@ -35,7 +35,6 @@
hosted: http://your-package-server.com
version: '>=0.4.0 <1.0.0'
analyzer: '0.24.0-dev.1'
- cli_util: '>=0.0.1 <0.1.0'
semver: '>=0.2.0 <0.3.0'
yaml: '>=2.1.2 <3.0.0'
kittens:
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 76fd405..ebd48c9 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -2026,6 +2026,9 @@
_'{0}' can't be used to name both a type variable and the class in which the
type variable is defined._
+_'{0}' can't be used to name both a type variable and the enum in which the type
+variable is defined._
+
_'{0}' can't be used to name both a type variable and the extension in which the
type variable is defined._
@@ -2059,6 +2062,8 @@
_'{0}' can't be used to name both a type variable and a member in this class._
+_'{0}' can't be used to name both a type variable and a member in this enum._
+
_'{0}' can't be used to name both a type variable and a member in this
extension._
@@ -8830,7 +8835,7 @@
#### Description
The analyzer produces this diagnostic when a `switch` statement for an enum
-doesn't include an option for one of the values in the enumeration.
+doesn't include an option for one of the values in the enum.
Note that `null` is always a possible value for an enum and therefore also
must be handled.
diff --git a/pkg/analyzer/tool/summary/build_sdk_summaries.dart b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
index 746feb2..da7a3af 100644
--- a/pkg/analyzer/tool/summary/build_sdk_summaries.dart
+++ b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
@@ -6,7 +6,7 @@
import 'package:analyzer/dart/sdk/build_sdk_summary.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:cli_util/cli_util.dart';
+import 'package:analyzer/src/util/sdk.dart';
void main(List<String> args) {
String command;
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 4ad9d00..a7278e1 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -329,7 +329,7 @@
}
// Infer if unspecified.
- sdkPath ??= getSdkPath(args);
+ sdkPath ??= getSdkPath();
var pathContext = resourceProvider.pathContext;
options.dartSdkPath = file_paths.absoluteNormalized(pathContext, sdkPath);
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 61b9776..524dae5 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -612,6 +612,23 @@
/// if the parameterName field is omitted.
String? parameterType;
+ /// This field is omitted if getSuggestions was used rather than
+ /// getSuggestions2.
+ ///
+ /// This field is omitted if this suggestion corresponds to a locally
+ /// declared element.
+ ///
+ /// If this suggestion corresponds to an already imported element, then this
+ /// field is the URI of a library that provides this element, not the URI of
+ /// the library where the element is declared.
+ ///
+ /// If this suggestion corresponds to an element from a not yet imported
+ /// library, this field is the URI of a library that could be imported to
+ /// make this suggestion accessible in the file where completion was
+ /// requested, such as package:foo/bar.dart or
+ /// file:///home/me/workspace/foo/test/bar_test.dart.
+ String? libraryUri;
+
/// True if the suggestion is for an element from a not yet imported library.
/// This field is omitted if the element is declared locally, or is from
/// library is already imported, so that the suggestion can be inserted as
@@ -642,6 +659,7 @@
this.hasNamedParameters,
this.parameterName,
this.parameterType,
+ this.libraryUri,
this.isNotImported});
factory CompletionSuggestion.fromJson(
@@ -781,6 +799,11 @@
parameterType = jsonDecoder.decodeString(
jsonPath + '.parameterType', json['parameterType']);
}
+ String? libraryUri;
+ if (json.containsKey('libraryUri')) {
+ libraryUri = jsonDecoder.decodeString(
+ jsonPath + '.libraryUri', json['libraryUri']);
+ }
bool? isNotImported;
if (json.containsKey('isNotImported')) {
isNotImported = jsonDecoder.decodeBool(
@@ -804,6 +827,7 @@
hasNamedParameters: hasNamedParameters,
parameterName: parameterName,
parameterType: parameterType,
+ libraryUri: libraryUri,
isNotImported: isNotImported);
} else {
throw jsonDecoder.mismatch(jsonPath, 'CompletionSuggestion', json);
@@ -884,6 +908,10 @@
if (parameterType != null) {
result['parameterType'] = parameterType;
}
+ var libraryUri = this.libraryUri;
+ if (libraryUri != null) {
+ result['libraryUri'] = libraryUri;
+ }
var isNotImported = this.isNotImported;
if (isNotImported != null) {
result['isNotImported'] = isNotImported;
@@ -923,6 +951,7 @@
hasNamedParameters == other.hasNamedParameters &&
parameterName == other.parameterName &&
parameterType == other.parameterType &&
+ libraryUri == other.libraryUri &&
isNotImported == other.isNotImported;
}
return false;
@@ -953,6 +982,7 @@
hasNamedParameters,
parameterName,
parameterType,
+ libraryUri,
isNotImported,
]);
}
@@ -1234,17 +1264,12 @@
/// this field will not be defined.
String? aliasedType;
- /// If the element belongs to a library, the URI of the library. Otherwise,
- /// this field will not be defined.
- String? libraryUri;
-
Element(this.kind, this.name, this.flags,
{this.location,
this.parameters,
this.returnType,
this.typeParameters,
- this.aliasedType,
- this.libraryUri});
+ this.aliasedType});
factory Element.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -1294,18 +1319,12 @@
aliasedType = jsonDecoder.decodeString(
jsonPath + '.aliasedType', json['aliasedType']);
}
- String? libraryUri;
- if (json.containsKey('libraryUri')) {
- libraryUri = jsonDecoder.decodeString(
- jsonPath + '.libraryUri', json['libraryUri']);
- }
return Element(kind, name, flags,
location: location,
parameters: parameters,
returnType: returnType,
typeParameters: typeParameters,
- aliasedType: aliasedType,
- libraryUri: libraryUri);
+ aliasedType: aliasedType);
} else {
throw jsonDecoder.mismatch(jsonPath, 'Element', json);
}
@@ -1344,10 +1363,6 @@
if (aliasedType != null) {
result['aliasedType'] = aliasedType;
}
- var libraryUri = this.libraryUri;
- if (libraryUri != null) {
- result['libraryUri'] = libraryUri;
- }
return result;
}
@@ -1364,8 +1379,7 @@
parameters == other.parameters &&
returnType == other.returnType &&
typeParameters == other.typeParameters &&
- aliasedType == other.aliasedType &&
- libraryUri == other.libraryUri;
+ aliasedType == other.aliasedType;
}
return false;
}
@@ -1380,7 +1394,6 @@
returnType,
typeParameters,
aliasedType,
- libraryUri,
);
}
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index cdb3f12..cfa4524 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -165,6 +165,7 @@
'hasNamedParameters': isBool,
'parameterName': isString,
'parameterType': isString,
+ 'libraryUri': isString,
'isNotImported': isBool
}));
@@ -237,8 +238,7 @@
'parameters': isString,
'returnType': isString,
'typeParameters': isString,
- 'aliasedType': isString,
- 'libraryUri': isString
+ 'aliasedType': isString
}));
/// ElementKind
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 969a0ee..e284b4f 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -380,6 +380,29 @@
omitted if the parameterName field is omitted.
</p>
</field>
+ <field name="libraryUri" experimental="true" optional="true">
+ <ref>String</ref>
+ <p>
+ This field is omitted if <tt>getSuggestions</tt> was used rather
+ than <tt>getSuggestions2</tt>.
+ </p>
+ <p>
+ This field is omitted if this suggestion corresponds to a locally
+ declared element.
+ </p>
+ <p>
+ If this suggestion corresponds to an already imported element,
+ then this field is the URI of a library that provides this element,
+ not the URI of the library where the element is declared.
+ </p>
+ <p>
+ If this suggestion corresponds to an element from a not yet
+ imported library, this field is the URI of a library that could be
+ imported to make this suggestion accessible in the file where
+ completion was requested, such as <tt>package:foo/bar.dart</tt> or
+ <tt>file:///home/me/workspace/foo/test/bar_test.dart</tt>.
+ </p>
+ </field>
<field name="isNotImported" optional="true" experimental="true">
<ref>bool</ref>
<p>
@@ -563,13 +586,6 @@
Otherwise this field will not be defined.
</p>
</field>
- <field name="libraryUri" optional="true" experimental="true">
- <ref>String</ref>
- <p>
- If the element belongs to a library, the URI of the library.
- Otherwise, this field will not be defined.
- </p>
- </field>
</object>
</type>
<type name="ElementKind">
diff --git a/pkg/compiler/lib/src/common/elements.dart b/pkg/compiler/lib/src/common/elements.dart
index 734b23c..b33db18 100644
--- a/pkg/compiler/lib/src/common/elements.dart
+++ b/pkg/compiler/lib/src/common/elements.dart
@@ -16,826 +16,263 @@
/// The common elements and types in Dart.
abstract class CommonElements {
- DartTypes get dartTypes;
+ final DartTypes dartTypes;
+ final ElementEnvironment _env;
+ ClassEntity _objectClass;
+ ClassEntity _boolClass;
+ ClassEntity _numClass;
+ ClassEntity _intClass;
+ ClassEntity _doubleClass;
+ ClassEntity _stringClass;
+ ClassEntity _functionClass;
+ ClassEntity _resourceClass;
+ ClassEntity _symbolClass;
+ ClassEntity _nullClass;
+ ClassEntity _typeClass;
+ ClassEntity _stackTraceClass;
+ ClassEntity _listClass;
+ ClassEntity _setClass;
+ ClassEntity _mapClass;
+ ClassEntity _unmodifiableSetClass;
+ ClassEntity _iterableClass;
+ ClassEntity _futureClass;
+ ClassEntity _streamClass;
+ LibraryEntity _coreLibrary;
+ LibraryEntity _asyncLibrary;
+ LibraryEntity _mirrorsLibrary;
+ LibraryEntity _typedDataLibrary;
+ LibraryEntity _jsHelperLibrary;
+ LibraryEntity _lateHelperLibrary;
+ LibraryEntity _foreignLibrary;
+ LibraryEntity _rtiLibrary;
+ LibraryEntity _interceptorsLibrary;
+ LibraryEntity _internalLibrary;
+ LibraryEntity _dartJsAnnotationsLibrary;
+ LibraryEntity _dartJsLibrary;
+ LibraryEntity _packageJsLibrary;
+ ClassEntity _typedDataClass;
+ ConstructorEntity _symbolConstructorTarget;
+ bool _computedSymbolConstructorDependencies = false;
+ ConstructorEntity _symbolConstructorImplementationTarget;
+ FunctionEntity _identicalFunction;
+ ClassEntity _mapLiteralClass;
+ ConstructorEntity _mapLiteralConstructor;
+ ConstructorEntity _mapLiteralConstructorEmpty;
+ FunctionEntity _mapLiteralUntypedMaker;
+ FunctionEntity _mapLiteralUntypedEmptyMaker;
+ ClassEntity _setLiteralClass;
+ ConstructorEntity _setLiteralConstructor;
+ ConstructorEntity _setLiteralConstructorEmpty;
+ FunctionEntity _setLiteralUntypedMaker;
+ FunctionEntity _setLiteralUntypedEmptyMaker;
+ FunctionEntity _objectNoSuchMethod;
+ FunctionEntity _syncStarIterableFactory;
+ FunctionEntity _asyncAwaitCompleterFactory;
+ FunctionEntity _asyncStarStreamControllerFactory;
+ ClassEntity _jsInterceptorClass;
+ ClassEntity _jsStringClass;
+ ClassEntity _jsArrayClass;
+ ClassEntity _jsNumberClass;
+ ClassEntity _jsIntClass;
+ ClassEntity _jsNumNotIntClass;
+ ClassEntity _jsNullClass;
+ ClassEntity _jsBoolClass;
+ ClassEntity _jsPlainJavaScriptObjectClass;
+ ClassEntity _jsUnknownJavaScriptObjectClass;
+ ClassEntity _jsJavaScriptFunctionClass;
+ ClassEntity _jsLegacyJavaScriptObjectClass;
+ ClassEntity _jsJavaScriptObjectClass;
+ ClassEntity _jsIndexableClass;
+ ClassEntity _jsMutableIndexableClass;
+ ClassEntity _jsMutableArrayClass;
+ ClassEntity _jsFixedArrayClass;
+ ClassEntity _jsExtendableArrayClass;
+ ClassEntity _jsUnmodifiableArrayClass;
+ ClassEntity _jsPositiveIntClass;
+ ClassEntity _jsUInt32Class;
+ ClassEntity _jsUInt31Class;
+ FunctionEntity _getNativeInterceptorMethod;
+ ConstructorEntity _jsArrayTypedConstructor;
+ ClassEntity _closureClass;
+ ClassEntity _closureClass0Args;
+ ClassEntity _closureClass2Args;
+ ClassEntity _boundClosureClass;
+ ClassEntity _typeLiteralClass;
+ ClassEntity _constMapLiteralClass;
+ ClassEntity _constSetLiteralClass;
+ ClassEntity _jsInvocationMirrorClass;
+ ClassEntity _requiredSentinelClass;
+ MemberEntity _invocationTypeArgumentGetter;
+ ClassEntity _jsIndexingBehaviorInterface;
+ ClassEntity _nativeAnnotationClass;
+ FunctionEntity _assertTest;
+ FunctionEntity _assertThrow;
+ FunctionEntity _assertHelper;
+ FunctionEntity _assertUnreachableMethod;
+ FunctionEntity _getIsolateAffinityTagMarker;
+ FunctionEntity _requiresPreambleMarker;
+ FunctionEntity _rawStartupMetrics;
+ FunctionEntity _setArrayType;
+ FunctionEntity _findType;
+ FunctionEntity _instanceType;
+ FunctionEntity _arrayInstanceType;
+ FunctionEntity _simpleInstanceType;
+ FunctionEntity _typeLiteralMaker;
+ FunctionEntity _checkTypeBound;
+ FieldEntity _rtiAsField;
+ FieldEntity _rtiIsField;
+ FieldEntity _rtiRestField;
+ FieldEntity _rtiPrecomputed1Field;
+ FunctionEntity _rtiEvalMethod;
+ FunctionEntity _rtiBindMethod;
+ FunctionEntity _rtiAddRulesMethod;
+ FunctionEntity _rtiAddErasedTypesMethod;
+ FunctionEntity _rtiAddTypeParameterVariancesMethod;
+ FunctionEntity _generalIsTestImplementation;
+ FunctionEntity _generalAsCheckImplementation;
+ FunctionEntity _generalNullableAsCheckImplementation;
+ FunctionEntity _specializedIsObject;
+ FunctionEntity _specializedAsObject;
+ FunctionEntity _generalNullableIsTestImplementation;
+ ClassEntity _symbolImplementationClass;
+ ClassEntity _externalNameClass;
+ ClassEntity _jsGetNameEnum;
+ FunctionEntity _jsAllowInterop1;
+ FunctionEntity _jsAllowInterop2;
+ FieldEntity _symbolImplementationField;
+ FunctionEntity _cachedCheckConcurrentModificationError;
+
+ CommonElements(this.dartTypes, this._env);
/// The `Object` class defined in 'dart:core'.
- ClassEntity get objectClass;
+ ClassEntity get objectClass =>
+ _objectClass ??= _findClass(coreLibrary, 'Object');
/// The `bool` class defined in 'dart:core'.
- ClassEntity get boolClass;
+ ClassEntity get boolClass => _boolClass ??= _findClass(coreLibrary, 'bool');
/// The `num` class defined in 'dart:core'.
- ClassEntity get numClass;
+ ClassEntity get numClass => _numClass ??= _findClass(coreLibrary, 'num');
/// The `int` class defined in 'dart:core'.
- ClassEntity get intClass;
+ ClassEntity get intClass => _intClass ??= _findClass(coreLibrary, 'int');
/// The `double` class defined in 'dart:core'.
- ClassEntity get doubleClass;
+ ClassEntity get doubleClass =>
+ _doubleClass ??= _findClass(coreLibrary, 'double');
/// The `String` class defined in 'dart:core'.
- ClassEntity get stringClass;
+ ClassEntity get stringClass =>
+ _stringClass ??= _findClass(coreLibrary, 'String');
/// The `Function` class defined in 'dart:core'.
- ClassEntity get functionClass;
+ ClassEntity get functionClass =>
+ _functionClass ??= _findClass(coreLibrary, 'Function');
/// The `Resource` class defined in 'dart:core'.
- ClassEntity get resourceClass;
+ ClassEntity get resourceClass =>
+ _resourceClass ??= _findClass(coreLibrary, 'Resource');
/// The `Symbol` class defined in 'dart:core'.
- ClassEntity get symbolClass;
+ ClassEntity get symbolClass =>
+ _symbolClass ??= _findClass(coreLibrary, 'Symbol');
/// The `Null` class defined in 'dart:core'.
- ClassEntity get nullClass;
+ ClassEntity get nullClass => _nullClass ??= _findClass(coreLibrary, 'Null');
/// The `Type` class defined in 'dart:core'.
- ClassEntity get typeClass;
+ ClassEntity get typeClass => _typeClass ??= _findClass(coreLibrary, 'Type');
/// The `StackTrace` class defined in 'dart:core';
- ClassEntity get stackTraceClass;
+ ClassEntity get stackTraceClass =>
+ _stackTraceClass ??= _findClass(coreLibrary, 'StackTrace');
/// The `List` class defined in 'dart:core';
- ClassEntity get listClass;
+ ClassEntity get listClass => _listClass ??= _findClass(coreLibrary, 'List');
/// The `Set` class defined in 'dart:core';
- ClassEntity get setClass;
+ ClassEntity get setClass => _setClass ??= _findClass(coreLibrary, 'Set');
/// The `Map` class defined in 'dart:core';
- ClassEntity get mapClass;
+ ClassEntity get mapClass => _mapClass ??= _findClass(coreLibrary, 'Map');
/// The `Set` class defined in 'dart:core';
- ClassEntity get unmodifiableSetClass;
+ ClassEntity get unmodifiableSetClass => _unmodifiableSetClass ??=
+ _findClass(_env.lookupLibrary(Uris.dart_collection), '_UnmodifiableSet');
/// The `Iterable` class defined in 'dart:core';
- ClassEntity get iterableClass;
+ ClassEntity get iterableClass =>
+ _iterableClass ??= _findClass(coreLibrary, 'Iterable');
/// The `Future` class defined in 'async';.
- ClassEntity get futureClass;
+ ClassEntity get futureClass =>
+ _futureClass ??= _findClass(asyncLibrary, 'Future');
/// The `Stream` class defined in 'async';
- ClassEntity get streamClass;
+ ClassEntity get streamClass =>
+ _streamClass ??= _findClass(asyncLibrary, 'Stream');
/// The dart:core library.
- LibraryEntity get coreLibrary;
+ LibraryEntity get coreLibrary =>
+ _coreLibrary ??= _env.lookupLibrary(Uris.dart_core, required: true);
/// The dart:async library.
- LibraryEntity get asyncLibrary;
+ LibraryEntity get asyncLibrary =>
+ _asyncLibrary ??= _env.lookupLibrary(Uris.dart_async);
/// The dart:mirrors library.
- LibraryEntity get mirrorsLibrary;
+ /// Null if the program doesn't access dart:mirrors.
+ LibraryEntity get mirrorsLibrary =>
+ _mirrorsLibrary ??= _env.lookupLibrary(Uris.dart_mirrors);
/// The dart:typed_data library.
- LibraryEntity get typedDataLibrary;
+ LibraryEntity get typedDataLibrary =>
+ _typedDataLibrary ??= _env.lookupLibrary(Uris.dart__native_typed_data);
/// The dart:_js_helper library.
- LibraryEntity get jsHelperLibrary;
+ LibraryEntity get jsHelperLibrary =>
+ _jsHelperLibrary ??= _env.lookupLibrary(Uris.dart__js_helper);
/// The dart:_late_helper library
- LibraryEntity get lateHelperLibrary;
+ LibraryEntity get lateHelperLibrary =>
+ _lateHelperLibrary ??= _env.lookupLibrary(Uris.dart__late_helper);
/// The dart:_interceptors library.
- LibraryEntity get interceptorsLibrary;
+ LibraryEntity get interceptorsLibrary =>
+ _interceptorsLibrary ??= _env.lookupLibrary(Uris.dart__interceptors);
/// The dart:_foreign_helper library.
- LibraryEntity get foreignLibrary;
+ LibraryEntity get foreignLibrary =>
+ _foreignLibrary ??= _env.lookupLibrary(Uris.dart__foreign_helper);
/// The dart:_internal library.
- LibraryEntity get rtiLibrary;
+ LibraryEntity get rtiLibrary =>
+ _rtiLibrary ??= _env.lookupLibrary(Uris.dart__rti, required: true);
/// The dart:_internal library.
- LibraryEntity get internalLibrary;
+ LibraryEntity get internalLibrary => _internalLibrary ??=
+ _env.lookupLibrary(Uris.dart__internal, required: true);
/// The dart:js library.
- LibraryEntity get dartJsLibrary;
+ LibraryEntity get dartJsLibrary =>
+ _dartJsLibrary ??= _env.lookupLibrary(Uris.dart_js);
/// The package:js library.
- LibraryEntity get packageJsLibrary;
+ LibraryEntity get packageJsLibrary =>
+ _packageJsLibrary ??= _env.lookupLibrary(Uris.package_js);
/// The dart:_js_annotations library.
- LibraryEntity get dartJsAnnotationsLibrary;
+ LibraryEntity get dartJsAnnotationsLibrary => _dartJsAnnotationsLibrary ??=
+ _env.lookupLibrary(Uris.dart__js_annotations);
/// The `NativeTypedData` class from dart:typed_data.
- ClassEntity get typedDataClass;
+ ClassEntity get typedDataClass =>
+ _typedDataClass ??= _findClass(typedDataLibrary, 'NativeTypedData');
/// Constructor of the `Symbol` class in dart:internal.
///
/// This getter will ensure that `Symbol` is resolved and lookup the
/// constructor on demand.
- ConstructorEntity get symbolConstructorTarget;
-
- /// Whether [element] is the same as [symbolConstructor].
- ///
- /// Used to check for the constructor without computing it until it is likely
- /// to be seen.
- bool isSymbolConstructor(ConstructorEntity element);
-
- /// The function `identical` in dart:core.
- FunctionEntity get identicalFunction;
-
- /// Whether [element] is the `Function.apply` method.
- ///
- /// This will not resolve the apply method if it hasn't been seen yet during
- /// compilation.
- bool isFunctionApplyMethod(MemberEntity element);
-
- /// The `dynamic` type.
- DynamicType get dynamicType;
-
- /// The `Object` type defined in 'dart:core'.
- InterfaceType get objectType;
-
- /// The `bool` type defined in 'dart:core'.
- InterfaceType get boolType;
-
- /// The `num` type defined in 'dart:core'.
- InterfaceType get numType;
-
- /// The `int` type defined in 'dart:core'.
- InterfaceType get intType;
-
- /// The `double` type defined in 'dart:core'.
- InterfaceType get doubleType;
-
- /// The `String` type defined in 'dart:core'.
- InterfaceType get stringType;
-
- /// The `Symbol` type defined in 'dart:core'.
- InterfaceType get symbolType;
-
- /// The `Function` type defined in 'dart:core'.
- InterfaceType get functionType;
-
- /// The `Null` type defined in 'dart:core'.
- InterfaceType get nullType;
-
- /// The `Type` type defined in 'dart:core'.
- InterfaceType get typeType;
-
- InterfaceType get typeLiteralType;
-
- /// The `StackTrace` type defined in 'dart:core';
- InterfaceType get stackTraceType;
-
- /// Returns an instance of the `List` type defined in 'dart:core' with
- /// [elementType] as its type argument.
- ///
- /// If no type argument is provided, the canonical raw type is returned.
- InterfaceType listType([DartType elementType]);
-
- /// Returns an instance of the `Set` type defined in 'dart:core' with
- /// [elementType] as its type argument.
- ///
- /// If no type argument is provided, the canonical raw type is returned.
- InterfaceType setType([DartType elementType]);
-
- /// Returns an instance of the `Map` type defined in 'dart:core' with
- /// [keyType] and [valueType] as its type arguments.
- ///
- /// If no type arguments are provided, the canonical raw type is returned.
- InterfaceType mapType([DartType keyType, DartType valueType]);
-
- /// Returns an instance of the `Iterable` type defined in 'dart:core' with
- /// [elementType] as its type argument.
- ///
- /// If no type argument is provided, the canonical raw type is returned.
- InterfaceType iterableType([DartType elementType]);
-
- /// Returns an instance of the `Future` type defined in 'dart:async' with
- /// [elementType] as its type argument.
- ///
- /// If no type argument is provided, the canonical raw type is returned.
- InterfaceType futureType([DartType elementType]);
-
- /// Returns an instance of the `Stream` type defined in 'dart:async' with
- /// [elementType] as its type argument.
- ///
- /// If no type argument is provided, the canonical raw type is returned.
- InterfaceType streamType([DartType elementType]);
-
- InterfaceType getConstantListTypeFor(InterfaceType sourceType);
-
- InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
- {bool onlyStringKeys = false});
-
- InterfaceType getConstantSetTypeFor(InterfaceType sourceType);
-
- FieldEntity get symbolField;
-
- InterfaceType get symbolImplementationType;
-
- // From dart:core
- ClassEntity get mapLiteralClass;
- ConstructorEntity get mapLiteralConstructor;
- ConstructorEntity get mapLiteralConstructorEmpty;
- FunctionEntity get mapLiteralUntypedMaker;
- FunctionEntity get mapLiteralUntypedEmptyMaker;
-
- ClassEntity get setLiteralClass;
- ConstructorEntity get setLiteralConstructor;
- ConstructorEntity get setLiteralConstructorEmpty;
- FunctionEntity get setLiteralUntypedMaker;
- FunctionEntity get setLiteralUntypedEmptyMaker;
-
- FunctionEntity get objectNoSuchMethod;
-
- bool isDefaultNoSuchMethodImplementation(FunctionEntity element);
-
- // From dart:async
- FunctionEntity get asyncHelperStartSync;
- FunctionEntity get asyncHelperAwait;
- FunctionEntity get asyncHelperReturn;
- FunctionEntity get asyncHelperRethrow;
-
- FunctionEntity get wrapBody;
-
- FunctionEntity get yieldStar;
-
- FunctionEntity get yieldSingle;
-
- FunctionEntity get syncStarUncaughtError;
-
- FunctionEntity get asyncStarHelper;
-
- FunctionEntity get streamOfController;
-
- FunctionEntity get endOfIteration;
-
- ClassEntity get syncStarIterable;
-
- ClassEntity get futureImplementation;
-
- ClassEntity get controllerStream;
-
- ClassEntity get streamIterator;
-
- ConstructorEntity get streamIteratorConstructor;
-
- FunctionEntity get syncStarIterableFactory;
-
- FunctionEntity get asyncAwaitCompleterFactory;
-
- FunctionEntity get asyncStarStreamControllerFactory;
-
- ClassEntity get jsInterceptorClass;
-
- ClassEntity get jsStringClass;
-
- ClassEntity get jsArrayClass;
-
- ClassEntity get jsNumberClass;
-
- ClassEntity get jsIntClass;
-
- ClassEntity get jsNumNotIntClass;
-
- ClassEntity get jsNullClass;
-
- ClassEntity get jsBoolClass;
-
- ClassEntity get jsPlainJavaScriptObjectClass;
-
- ClassEntity get jsUnknownJavaScriptObjectClass;
-
- ClassEntity get jsJavaScriptFunctionClass;
-
- InterfaceType get jsJavaScriptFunctionType;
-
- ClassEntity get jsLegacyJavaScriptObjectClass;
-
- ClassEntity get jsJavaScriptObjectClass;
-
- ClassEntity get jsIndexableClass;
-
- ClassEntity get jsMutableIndexableClass;
-
- ClassEntity get jsMutableArrayClass;
-
- ClassEntity get jsFixedArrayClass;
-
- ClassEntity get jsExtendableArrayClass;
-
- ClassEntity get jsUnmodifiableArrayClass;
-
- ClassEntity get jsPositiveIntClass;
-
- ClassEntity get jsUInt32Class;
-
- ClassEntity get jsUInt31Class;
-
- /// Returns `true` member is the 'findIndexForNativeSubclassType' method
- /// declared in `dart:_interceptors`.
- bool isFindIndexForNativeSubclassType(MemberEntity member);
-
- FunctionEntity get getNativeInterceptorMethod;
-
- ConstructorEntity get jsArrayTypedConstructor;
-
- // From dart:_js_helper
- // TODO(johnniwinther): Avoid the need for this (from [CheckedModeHelper]).
- FunctionEntity findHelperFunction(String name);
-
- ClassEntity get closureClass;
- ClassEntity get closureClass0Args;
- ClassEntity get closureClass2Args;
-
- ClassEntity get boundClosureClass;
-
- ClassEntity get typeLiteralClass;
-
- ClassEntity get constMapLiteralClass;
-
- ClassEntity get constSetLiteralClass;
-
- ClassEntity get jsInvocationMirrorClass;
-
- ClassEntity get requiredSentinelClass;
-
- InterfaceType get requiredSentinelType;
-
- MemberEntity get invocationTypeArgumentGetter;
-
- /// Interface used to determine if an object has the JavaScript
- /// indexing behavior. The interface is only visible to specific libraries.
- ClassEntity get jsIndexingBehaviorInterface;
-
- ClassEntity get stackTraceHelperClass;
-
- ClassEntity get constantMapClass;
- ClassEntity get constantStringMapClass;
- ClassEntity get generalConstantMapClass;
-
- ClassEntity get annotationCreatesClass;
-
- ClassEntity get annotationReturnsClass;
-
- ClassEntity get annotationJSNameClass;
-
- /// The class for native annotations defined in dart:_js_helper.
- ClassEntity get nativeAnnotationClass;
-
- FunctionEntity get assertTest;
-
- FunctionEntity get assertThrow;
-
- FunctionEntity get assertHelper;
-
- FunctionEntity get assertUnreachableMethod;
-
- /// Holds the method "getIsolateAffinityTag" when dart:_js_helper has been
- /// loaded.
- FunctionEntity get getIsolateAffinityTagMarker;
-
- /// Holds the method "requiresPreamble" in _js_helper.
- FunctionEntity get requiresPreambleMarker;
-
- /// Holds the method "_rawStartupMetrics" in _js_helper.
- FunctionEntity get rawStartupMetrics;
-
- FunctionEntity get loadLibraryWrapper;
-
- FunctionEntity get loadDeferredLibrary;
-
- FunctionEntity get boolConversionCheck;
-
- FunctionEntity get traceHelper;
-
- FunctionEntity get closureFromTearOff;
-
- FunctionEntity get isJsIndexable;
-
- FunctionEntity get throwIllegalArgumentException;
-
- FunctionEntity get throwIndexOutOfRangeException;
-
- FunctionEntity get exceptionUnwrapper;
-
- FunctionEntity get throwUnsupportedError;
-
- FunctionEntity get throwTypeError;
-
- /// Recognizes the `checkConcurrentModificationError` helper without needing
- /// it to be resolved.
- bool isCheckConcurrentModificationError(MemberEntity member);
-
- FunctionEntity get checkConcurrentModificationError;
-
- FunctionEntity get throwConcurrentModificationError;
-
- FunctionEntity get stringInterpolationHelper;
-
- FunctionEntity get wrapExceptionHelper;
-
- FunctionEntity get throwExpressionHelper;
-
- FunctionEntity get closureConverter;
-
- FunctionEntity get traceFromException;
-
- FunctionEntity get checkDeferredIsLoaded;
-
- FunctionEntity get throwNoSuchMethod;
-
- FunctionEntity get createRuntimeType;
-
- FunctionEntity get fallThroughError;
-
- FunctionEntity get createInvocationMirror;
-
- FunctionEntity get createUnmangledInvocationMirror;
-
- FunctionEntity get cyclicThrowHelper;
-
- FunctionEntity get defineProperty;
-
- FunctionEntity get throwLateFieldADI;
-
- bool isExtractTypeArguments(FunctionEntity member);
-
- ClassEntity getInstantiationClass(int typeArgumentCount);
-
- FunctionEntity getInstantiateFunction(int typeArgumentCount);
-
- FunctionEntity get convertMainArgumentList;
-
- // From dart:_rti
-
- FunctionEntity get setArrayType;
-
- FunctionEntity get findType;
- FunctionEntity get instanceType;
- FunctionEntity get arrayInstanceType;
- FunctionEntity get simpleInstanceType;
- FunctionEntity get typeLiteralMaker;
- FunctionEntity get checkTypeBound;
- FieldEntity get rtiAsField;
- FieldEntity get rtiIsField;
- FieldEntity get rtiRestField;
- FieldEntity get rtiPrecomputed1Field;
- FunctionEntity get rtiEvalMethod;
- FunctionEntity get rtiBindMethod;
- FunctionEntity get rtiAddRulesMethod;
- FunctionEntity get rtiAddErasedTypesMethod;
- FunctionEntity get rtiAddTypeParameterVariancesMethod;
-
- FunctionEntity get installSpecializedIsTest;
- FunctionEntity get installSpecializedAsCheck;
- FunctionEntity get generalIsTestImplementation;
- FunctionEntity get generalAsCheckImplementation;
- FunctionEntity get generalNullableIsTestImplementation;
- FunctionEntity get generalNullableAsCheckImplementation;
-
- FunctionEntity get specializedIsObject;
- FunctionEntity get specializedAsObject;
- FunctionEntity get specializedIsTop;
- FunctionEntity get specializedAsTop;
- FunctionEntity get specializedIsBool;
- FunctionEntity get specializedAsBool;
- FunctionEntity get specializedAsBoolLegacy;
- FunctionEntity get specializedAsBoolNullable;
- FunctionEntity get specializedAsDouble;
- FunctionEntity get specializedAsDoubleLegacy;
- FunctionEntity get specializedAsDoubleNullable;
- FunctionEntity get specializedIsInt;
- FunctionEntity get specializedAsInt;
- FunctionEntity get specializedAsIntLegacy;
- FunctionEntity get specializedAsIntNullable;
- FunctionEntity get specializedIsNum;
- FunctionEntity get specializedAsNum;
- FunctionEntity get specializedAsNumLegacy;
- FunctionEntity get specializedAsNumNullable;
- FunctionEntity get specializedIsString;
- FunctionEntity get specializedAsString;
- FunctionEntity get specializedAsStringLegacy;
- FunctionEntity get specializedAsStringNullable;
-
- FunctionEntity get instantiatedGenericFunctionTypeNewRti;
- FunctionEntity get closureFunctionType;
-
- // From dart:_internal
-
- ClassEntity get symbolImplementationClass;
-
- /// Used to annotate items that have the keyword "native".
- ClassEntity get externalNameClass;
-
- InterfaceType get externalNameType;
-
- // From dart:_js_embedded_names
-
- /// Holds the class for the [JsGetName] enum.
- ClassEntity get jsGetNameEnum;
-
- /// Returns `true` if [member] is a "foreign helper", that is, a member whose
- /// semantics is defined synthetically and not through Dart code.
- ///
- /// Most foreign helpers are located in the `dart:_foreign_helper` library.
- bool isForeignHelper(MemberEntity member);
-
- /// Returns `true` if [member] is the `createJsSentinel` function defined in
- /// dart:_foreign_helper.
- bool isCreateJsSentinel(MemberEntity member);
-
- /// Returns `true` if [member] is the `isJsSentinel` function defined in
- /// dart:_foreign_helper.
- bool isIsJsSentinel(MemberEntity member);
-
- /// Returns `true` if [member] is the `_lateReadCheck` function defined in
- /// dart:_internal.
- bool isLateReadCheck(MemberEntity member);
-
- /// Returns `true` if [member] is the `createSentinel` function defined in
- /// dart:_internal.
- bool isCreateSentinel(MemberEntity member);
-
- ClassEntity getDefaultSuperclass(
- ClassEntity cls, NativeBasicData nativeBasicData);
-
- // From package:js
- FunctionEntity get jsAllowInterop1;
-
- // From dart:_js_annotations;
- FunctionEntity get jsAllowInterop2;
-
- /// Returns `true` if [function] is `allowInterop`.
- ///
- /// This function can come from either `package:js` or `dart:_js_annotations`.
- bool isJsAllowInterop(FunctionEntity function);
-}
-
-abstract class KCommonElements implements CommonElements {
- // From package:js
- ClassEntity get jsAnnotationClass1;
- ClassEntity get jsAnonymousClass1;
-
- // From dart:_js_annotations
- ClassEntity get jsAnnotationClass2;
- ClassEntity get jsAnonymousClass2;
-
- /// Returns `true` if [cls] is a @JS() annotation.
- ///
- /// The class can come from either `package:js` or `dart:_js_annotations`.
- bool isJsAnnotationClass(ClassEntity cls);
-
- /// Returns `true` if [cls] is an @anonymous annotation.
- ///
- /// The class can come from either `package:js` or `dart:_js_annotations`.
- bool isJsAnonymousClass(ClassEntity cls);
-
- ClassEntity get pragmaClass;
- FieldEntity get pragmaClassNameField;
- FieldEntity get pragmaClassOptionsField;
-
- bool isCreateInvocationMirrorHelper(MemberEntity member);
-}
-
-abstract class JCommonElements implements CommonElements {
- /// Returns `true` if [element] is the unnamed constructor of `List`.
- ///
- /// This will not resolve the constructor if it hasn't been seen yet during
- /// compilation.
- bool isUnnamedListConstructor(ConstructorEntity element);
-
- /// Returns `true` if [element] is the named constructor of `List`,
- /// e.g. `List.of`.
- ///
- /// This will not resolve the constructor if it hasn't been seen yet during
- /// compilation.
- bool isNamedListConstructor(String name, ConstructorEntity element);
-
- /// Returns `true` if [element] is the named constructor of `JSArray`,
- /// e.g. `JSArray.fixed`.
- ///
- /// This will not resolve the constructor if it hasn't been seen yet during
- /// compilation.
- bool isNamedJSArrayConstructor(String name, ConstructorEntity element);
-
- bool isDefaultEqualityImplementation(MemberEntity element);
-
- /// Returns `true` if [selector] applies to `JSIndexable.length`.
- bool appliesToJsIndexableLength(Selector selector);
-
- FunctionEntity get jsArrayRemoveLast;
-
- FunctionEntity get jsArrayAdd;
-
- bool isJsStringSplit(MemberEntity member);
-
- /// Returns `true` if [selector] applies to `JSString.split` on [receiver]
- /// in the given [world].
- ///
- /// Returns `false` if `JSString.split` is not available.
- bool appliesToJsStringSplit(Selector selector, AbstractValue receiver,
- AbstractValueDomain abstractValueDomain);
-
- FunctionEntity get jsStringSplit;
-
- FunctionEntity get jsStringToString;
-
- FunctionEntity get jsStringOperatorAdd;
-
- ClassEntity get jsConstClass;
-
- /// Return `true` if [member] is the 'checkInt' function defined in
- /// dart:_js_helpers.
- bool isCheckInt(MemberEntity member);
-
- /// Return `true` if [member] is the 'checkNum' function defined in
- /// dart:_js_helpers.
- bool isCheckNum(MemberEntity member);
-
- /// Return `true` if [member] is the 'checkString' function defined in
- /// dart:_js_helpers.
- bool isCheckString(MemberEntity member);
-
- bool isInstantiationClass(ClassEntity cls);
-
- // From dart:_native_typed_data
-
- ClassEntity get typedArrayOfIntClass;
-
- ClassEntity get typedArrayOfDoubleClass;
-
- /// Holds the class for the [JsBuiltins] enum.
- ClassEntity get jsBuiltinEnum;
-
- bool isForeign(MemberEntity element);
-
- /// Returns `true` if the implementation of the 'operator ==' [function] is
- /// known to handle `null` as argument.
- bool operatorEqHandlesNullArgument(FunctionEntity function);
-}
-
-class CommonElementsImpl
- implements CommonElements, KCommonElements, JCommonElements {
- @override
- final DartTypes dartTypes;
- final ElementEnvironment _env;
-
- CommonElementsImpl(this.dartTypes, this._env);
-
- ClassEntity _objectClass;
- @override
- ClassEntity get objectClass =>
- _objectClass ??= _findClass(coreLibrary, 'Object');
-
- ClassEntity _boolClass;
- @override
- ClassEntity get boolClass => _boolClass ??= _findClass(coreLibrary, 'bool');
-
- ClassEntity _numClass;
- @override
- ClassEntity get numClass => _numClass ??= _findClass(coreLibrary, 'num');
-
- ClassEntity _intClass;
- @override
- ClassEntity get intClass => _intClass ??= _findClass(coreLibrary, 'int');
-
- ClassEntity _doubleClass;
- @override
- ClassEntity get doubleClass =>
- _doubleClass ??= _findClass(coreLibrary, 'double');
-
- ClassEntity _stringClass;
- @override
- ClassEntity get stringClass =>
- _stringClass ??= _findClass(coreLibrary, 'String');
-
- ClassEntity _functionClass;
- @override
- ClassEntity get functionClass =>
- _functionClass ??= _findClass(coreLibrary, 'Function');
-
- ClassEntity _resourceClass;
- @override
- ClassEntity get resourceClass =>
- _resourceClass ??= _findClass(coreLibrary, 'Resource');
-
- ClassEntity _symbolClass;
- @override
- ClassEntity get symbolClass =>
- _symbolClass ??= _findClass(coreLibrary, 'Symbol');
-
- ClassEntity _nullClass;
- @override
- ClassEntity get nullClass => _nullClass ??= _findClass(coreLibrary, 'Null');
-
- ClassEntity _typeClass;
- @override
- ClassEntity get typeClass => _typeClass ??= _findClass(coreLibrary, 'Type');
-
- ClassEntity _stackTraceClass;
- @override
- ClassEntity get stackTraceClass =>
- _stackTraceClass ??= _findClass(coreLibrary, 'StackTrace');
-
- ClassEntity _listClass;
- @override
- ClassEntity get listClass => _listClass ??= _findClass(coreLibrary, 'List');
-
- ClassEntity _setClass;
- @override
- ClassEntity get setClass => _setClass ??= _findClass(coreLibrary, 'Set');
-
- ClassEntity _mapClass;
- @override
- ClassEntity get mapClass => _mapClass ??= _findClass(coreLibrary, 'Map');
-
- ClassEntity _unmodifiableSetClass;
- @override
- ClassEntity get unmodifiableSetClass => _unmodifiableSetClass ??=
- _findClass(_env.lookupLibrary(Uris.dart_collection), '_UnmodifiableSet');
-
- ClassEntity _iterableClass;
- @override
- ClassEntity get iterableClass =>
- _iterableClass ??= _findClass(coreLibrary, 'Iterable');
-
- ClassEntity _futureClass;
- @override
- ClassEntity get futureClass =>
- _futureClass ??= _findClass(asyncLibrary, 'Future');
-
- ClassEntity _streamClass;
- @override
- ClassEntity get streamClass =>
- _streamClass ??= _findClass(asyncLibrary, 'Stream');
-
- LibraryEntity _coreLibrary;
- @override
- LibraryEntity get coreLibrary =>
- _coreLibrary ??= _env.lookupLibrary(Uris.dart_core, required: true);
-
- LibraryEntity _asyncLibrary;
- @override
- LibraryEntity get asyncLibrary =>
- _asyncLibrary ??= _env.lookupLibrary(Uris.dart_async);
-
- /// The dart:mirrors library.
- ///
- /// Null if the program doesn't access dart:mirrors.
- LibraryEntity _mirrorsLibrary;
- @override
- LibraryEntity get mirrorsLibrary =>
- _mirrorsLibrary ??= _env.lookupLibrary(Uris.dart_mirrors);
-
- LibraryEntity _typedDataLibrary;
- @override
- LibraryEntity get typedDataLibrary =>
- _typedDataLibrary ??= _env.lookupLibrary(Uris.dart__native_typed_data);
-
- LibraryEntity _jsHelperLibrary;
- @override
- LibraryEntity get jsHelperLibrary =>
- _jsHelperLibrary ??= _env.lookupLibrary(Uris.dart__js_helper);
-
- LibraryEntity _lateHelperLibrary;
- @override
- LibraryEntity get lateHelperLibrary =>
- _lateHelperLibrary ??= _env.lookupLibrary(Uris.dart__late_helper);
-
- LibraryEntity _interceptorsLibrary;
- @override
- LibraryEntity get interceptorsLibrary =>
- _interceptorsLibrary ??= _env.lookupLibrary(Uris.dart__interceptors);
-
- LibraryEntity _foreignLibrary;
- @override
- LibraryEntity get foreignLibrary =>
- _foreignLibrary ??= _env.lookupLibrary(Uris.dart__foreign_helper);
-
- LibraryEntity _rtiLibrary;
- @override
- LibraryEntity get rtiLibrary =>
- _rtiLibrary ??= _env.lookupLibrary(Uris.dart__rti, required: true);
-
- /// Reference to the internal library to lookup functions to always inline.
- LibraryEntity _internalLibrary;
- @override
- LibraryEntity get internalLibrary => _internalLibrary ??=
- _env.lookupLibrary(Uris.dart__internal, required: true);
-
- LibraryEntity _dartJsLibrary;
- @override
- LibraryEntity get dartJsLibrary =>
- _dartJsLibrary ??= _env.lookupLibrary(Uris.dart_js);
-
- LibraryEntity _packageJsLibrary;
- @override
- LibraryEntity get packageJsLibrary =>
- _packageJsLibrary ??= _env.lookupLibrary(Uris.package_js);
-
- LibraryEntity _dartJsAnnotationsLibrary;
- @override
- LibraryEntity get dartJsAnnotationsLibrary => _dartJsAnnotationsLibrary ??=
- _env.lookupLibrary(Uris.dart__js_annotations);
-
- ClassEntity _typedDataClass;
- @override
- ClassEntity get typedDataClass =>
- _typedDataClass ??= _findClass(typedDataLibrary, 'NativeTypedData');
-
- ConstructorEntity _symbolConstructorTarget;
- @override
ConstructorEntity get symbolConstructorTarget {
// TODO(johnniwinther): Kernel does not include redirecting factories
// so this cannot be found in kernel. Find a consistent way to handle
@@ -844,9 +281,6 @@
_findConstructor(symbolImplementationClass, '');
}
- bool _computedSymbolConstructorDependencies = false;
- ConstructorEntity _symbolConstructorImplementationTarget;
-
void _ensureSymbolConstructorDependencies() {
if (_computedSymbolConstructorDependencies) return;
_computedSymbolConstructorDependencies = true;
@@ -870,7 +304,10 @@
_findConstructor(symbolClass, '', required: false);
}
- @override
+ /// Whether [element] is the same as [symbolConstructor].
+ ///
+ /// Used to check for the constructor without computing it until it is likely
+ /// to be seen.
bool isSymbolConstructor(ConstructorEntity element) {
assert(element != null);
_ensureSymbolConstructorDependencies();
@@ -878,80 +315,59 @@
element == _symbolConstructorTarget;
}
- FunctionEntity _identicalFunction;
- @override
+ /// The function `identical` in dart:core.
FunctionEntity get identicalFunction =>
_identicalFunction ??= _findLibraryMember(coreLibrary, 'identical');
- @override
+ /// Whether [element] is the `Function.apply` method.
+ ///
+ /// This will not resolve the apply method if it hasn't been seen yet during
+ /// compilation.
bool isFunctionApplyMethod(MemberEntity element) =>
element.name == 'apply' && element.enclosingClass == functionClass;
- /// Returns `true` if [element] is the unnamed constructor of `List`.
- ///
- /// This will not resolve the constructor if it hasn't been seen yet during
- /// compilation.
- @override
- bool isUnnamedListConstructor(ConstructorEntity element) =>
- (element.name == '' && element.enclosingClass == listClass) ||
- (element.name == 'list' && element.enclosingClass == jsArrayClass);
-
- /// Returns `true` if [element] is the 'filled' constructor of `List`.
- ///
- /// This will not resolve the constructor if it hasn't been seen yet during
- /// compilation.
- @override
- bool isNamedListConstructor(String name, ConstructorEntity element) =>
- element.name == name && element.enclosingClass == listClass;
-
- /// Returns `true` if [element] is the [name]d constructor of `JSArray`.
- ///
- /// This will not resolve the constructor if it hasn't been seen yet during
- /// compilation.
- @override
- bool isNamedJSArrayConstructor(String name, ConstructorEntity element) =>
- element.name == name && element.enclosingClass == jsArrayClass;
-
- @override
+ /// The `dynamic` type.
DynamicType get dynamicType => _env.dynamicType;
- @override
+ /// The `Object` type defined in 'dart:core'.
InterfaceType get objectType => _getRawType(objectClass);
- @override
+ /// The `bool` type defined in 'dart:core'.
InterfaceType get boolType => _getRawType(boolClass);
- @override
+ /// The `num` type defined in 'dart:core'.
InterfaceType get numType => _getRawType(numClass);
- @override
+ /// The `int` type defined in 'dart:core'.
InterfaceType get intType => _getRawType(intClass);
- @override
+ /// The `double` type defined in 'dart:core'.
InterfaceType get doubleType => _getRawType(doubleClass);
- @override
+ /// The `String` type defined in 'dart:core'.
InterfaceType get stringType => _getRawType(stringClass);
- @override
+ /// The `Symbol` type defined in 'dart:core'.
InterfaceType get symbolType => _getRawType(symbolClass);
- @override
+ /// The `Function` type defined in 'dart:core'.
InterfaceType get functionType => _getRawType(functionClass);
- @override
+ /// The `Null` type defined in 'dart:core'.
InterfaceType get nullType => _getRawType(nullClass);
- @override
+ /// The `Type` type defined in 'dart:core'.
InterfaceType get typeType => _getRawType(typeClass);
- @override
InterfaceType get typeLiteralType => _getRawType(typeLiteralClass);
- @override
+ /// The `StackTrace` type defined in 'dart:core';
InterfaceType get stackTraceType => _getRawType(stackTraceClass);
- @override
+ /// Returns an instance of the `List` type defined in 'dart:core' with
+ /// [elementType] as its type argument.
+ ///
+ /// If no type argument is provided, the canonical raw type is returned.
InterfaceType listType([DartType elementType]) {
if (elementType == null) {
return _getRawType(listClass);
@@ -959,7 +375,10 @@
return _createInterfaceType(listClass, [elementType]);
}
- @override
+ /// Returns an instance of the `Set` type defined in 'dart:core' with
+ /// [elementType] as its type argument.
+ ///
+ /// If no type argument is provided, the canonical raw type is returned.
InterfaceType setType([DartType elementType]) {
if (elementType == null) {
return _getRawType(setClass);
@@ -967,7 +386,10 @@
return _createInterfaceType(setClass, [elementType]);
}
- @override
+ /// Returns an instance of the `Map` type defined in 'dart:core' with
+ /// [keyType] and [valueType] as its type arguments.
+ ///
+ /// If no type arguments are provided, the canonical raw type is returned.
InterfaceType mapType([DartType keyType, DartType valueType]) {
if (keyType == null && valueType == null) {
return _getRawType(mapClass);
@@ -979,7 +401,10 @@
return _createInterfaceType(mapClass, [keyType, valueType]);
}
- @override
+ /// Returns an instance of the `Iterable` type defined in 'dart:core' with
+ /// [elementType] as its type argument.
+ ///
+ /// If no type argument is provided, the canonical raw type is returned.
InterfaceType iterableType([DartType elementType]) {
if (elementType == null) {
return _getRawType(iterableClass);
@@ -987,7 +412,10 @@
return _createInterfaceType(iterableClass, [elementType]);
}
- @override
+ /// Returns an instance of the `Future` type defined in 'dart:async' with
+ /// [elementType] as its type argument.
+ ///
+ /// If no type argument is provided, the canonical raw type is returned.
InterfaceType futureType([DartType elementType]) {
if (elementType == null) {
return _getRawType(futureClass);
@@ -995,7 +423,10 @@
return _createInterfaceType(futureClass, [elementType]);
}
- @override
+ /// Returns an instance of the `Stream` type defined in 'dart:async' with
+ /// [elementType] as its type argument.
+ ///
+ /// If no type argument is provided, the canonical raw type is returned.
InterfaceType streamType([DartType elementType]) {
if (elementType == null) {
return _getRawType(streamClass);
@@ -1039,13 +470,11 @@
return _env.createInterfaceType(cls, typeArguments);
}
- @override
InterfaceType getConstantListTypeFor(InterfaceType sourceType) =>
dartTypes.treatAsRawType(sourceType)
? _env.getRawType(jsArrayClass)
: _env.createInterfaceType(jsArrayClass, sourceType.typeArguments);
- @override
InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
{bool onlyStringKeys = false}) {
ClassEntity classElement =
@@ -1057,33 +486,22 @@
}
}
- @override
InterfaceType getConstantSetTypeFor(InterfaceType sourceType) =>
dartTypes.treatAsRawType(sourceType)
? _env.getRawType(constSetLiteralClass)
: _env.createInterfaceType(
constSetLiteralClass, sourceType.typeArguments);
- @override
- FieldEntity get symbolField => symbolImplementationField;
+ /// Returns the field that holds the internal name in the implementation class
+ /// for `Symbol`.
+ FieldEntity get symbolField => _symbolImplementationField ??=
+ _env.lookupLocalClassMember(symbolImplementationClass, '_name',
+ required: true);
- @override
InterfaceType get symbolImplementationType =>
_env.getRawType(symbolImplementationClass);
- @override
- bool isDefaultEqualityImplementation(MemberEntity element) {
- assert(element.name == '==');
- ClassEntity classElement = element.enclosingClass;
- return classElement == objectClass ||
- classElement == jsInterceptorClass ||
- classElement == jsNullClass;
- }
-
// From dart:core
-
- ClassEntity _mapLiteralClass;
- @override
ClassEntity get mapLiteralClass {
if (_mapLiteralClass == null) {
_mapLiteralClass = _env.lookupClass(coreLibrary, 'LinkedHashMap');
@@ -1095,10 +513,6 @@
return _mapLiteralClass;
}
- ConstructorEntity _mapLiteralConstructor;
- ConstructorEntity _mapLiteralConstructorEmpty;
- FunctionEntity _mapLiteralUntypedMaker;
- FunctionEntity _mapLiteralUntypedEmptyMaker;
void _ensureMapLiteralHelpers() {
if (_mapLiteralConstructor != null) return;
@@ -1112,40 +526,29 @@
_env.lookupLocalClassMember(mapLiteralClass, '_makeEmpty');
}
- @override
ConstructorEntity get mapLiteralConstructor {
_ensureMapLiteralHelpers();
return _mapLiteralConstructor;
}
- @override
ConstructorEntity get mapLiteralConstructorEmpty {
_ensureMapLiteralHelpers();
return _mapLiteralConstructorEmpty;
}
- @override
FunctionEntity get mapLiteralUntypedMaker {
_ensureMapLiteralHelpers();
return _mapLiteralUntypedMaker;
}
- @override
FunctionEntity get mapLiteralUntypedEmptyMaker {
_ensureMapLiteralHelpers();
return _mapLiteralUntypedEmptyMaker;
}
- ClassEntity _setLiteralClass;
- @override
ClassEntity get setLiteralClass => _setLiteralClass ??=
_findClass(_env.lookupLibrary(Uris.dart_collection), 'LinkedHashSet');
- ConstructorEntity _setLiteralConstructor;
- ConstructorEntity _setLiteralConstructorEmpty;
- FunctionEntity _setLiteralUntypedMaker;
- FunctionEntity _setLiteralUntypedEmptyMaker;
-
void _ensureSetLiteralHelpers() {
if (_setLiteralConstructor != null) return;
@@ -1159,38 +562,31 @@
_env.lookupLocalClassMember(setLiteralClass, '_makeEmpty');
}
- @override
ConstructorEntity get setLiteralConstructor {
_ensureSetLiteralHelpers();
return _setLiteralConstructor;
}
- @override
ConstructorEntity get setLiteralConstructorEmpty {
_ensureSetLiteralHelpers();
return _setLiteralConstructorEmpty;
}
- @override
FunctionEntity get setLiteralUntypedMaker {
_ensureSetLiteralHelpers();
return _setLiteralUntypedMaker;
}
- @override
FunctionEntity get setLiteralUntypedEmptyMaker {
_ensureSetLiteralHelpers();
return _setLiteralUntypedEmptyMaker;
}
- FunctionEntity _objectNoSuchMethod;
- @override
FunctionEntity get objectNoSuchMethod {
return _objectNoSuchMethod ??=
_env.lookupLocalClassMember(objectClass, Identifiers.noSuchMethod_);
}
- @override
bool isDefaultNoSuchMethodImplementation(FunctionEntity element) {
ClassEntity classElement = element.enclosingClass;
return classElement == objectClass ||
@@ -1205,78 +601,59 @@
FunctionEntity _findAsyncHelperFunction(String name) =>
_findLibraryMember(asyncLibrary, name);
- @override
FunctionEntity get asyncHelperStartSync =>
_findAsyncHelperFunction("_asyncStartSync");
- @override
+
FunctionEntity get asyncHelperAwait =>
_findAsyncHelperFunction("_asyncAwait");
- @override
+
FunctionEntity get asyncHelperReturn =>
_findAsyncHelperFunction("_asyncReturn");
- @override
+
FunctionEntity get asyncHelperRethrow =>
_findAsyncHelperFunction("_asyncRethrow");
- @override
FunctionEntity get wrapBody =>
_findAsyncHelperFunction("_wrapJsFunctionForAsync");
- @override
FunctionEntity get yieldStar => _env.lookupLocalClassMember(
_findAsyncHelperClass("_IterationMarker"), "yieldStar");
- @override
FunctionEntity get yieldSingle => _env.lookupLocalClassMember(
_findAsyncHelperClass("_IterationMarker"), "yieldSingle");
- @override
FunctionEntity get syncStarUncaughtError => _env.lookupLocalClassMember(
_findAsyncHelperClass("_IterationMarker"), "uncaughtError");
- @override
FunctionEntity get asyncStarHelper =>
_findAsyncHelperFunction("_asyncStarHelper");
- @override
FunctionEntity get streamOfController =>
_findAsyncHelperFunction("_streamOfController");
- @override
FunctionEntity get endOfIteration => _env.lookupLocalClassMember(
_findAsyncHelperClass("_IterationMarker"), "endOfIteration");
- @override
ClassEntity get syncStarIterable =>
_findAsyncHelperClass("_SyncStarIterable");
- @override
ClassEntity get futureImplementation => _findAsyncHelperClass('_Future');
- @override
ClassEntity get controllerStream =>
_findAsyncHelperClass("_ControllerStream");
- @override
ClassEntity get streamIterator => _findAsyncHelperClass("StreamIterator");
- @override
ConstructorEntity get streamIteratorConstructor =>
_env.lookupConstructor(streamIterator, "");
- FunctionEntity _syncStarIterableFactory;
- @override
FunctionEntity get syncStarIterableFactory => _syncStarIterableFactory ??=
_findAsyncHelperFunction('_makeSyncStarIterable');
- FunctionEntity _asyncAwaitCompleterFactory;
- @override
FunctionEntity get asyncAwaitCompleterFactory =>
_asyncAwaitCompleterFactory ??=
_findAsyncHelperFunction('_makeAsyncAwaitCompleter');
- FunctionEntity _asyncStarStreamControllerFactory;
- @override
FunctionEntity get asyncStarStreamControllerFactory =>
_asyncStarStreamControllerFactory ??=
_findAsyncHelperFunction('_makeAsyncStarStreamController');
@@ -1288,256 +665,94 @@
FunctionEntity _findInterceptorsFunction(String name) =>
_findLibraryMember(interceptorsLibrary, name);
- ClassEntity _jsInterceptorClass;
- @override
ClassEntity get jsInterceptorClass =>
_jsInterceptorClass ??= _findInterceptorsClass('Interceptor');
- ClassEntity _jsStringClass;
- @override
ClassEntity get jsStringClass =>
_jsStringClass ??= _findInterceptorsClass('JSString');
- ClassEntity _jsArrayClass;
- @override
ClassEntity get jsArrayClass =>
_jsArrayClass ??= _findInterceptorsClass('JSArray');
- ClassEntity _jsNumberClass;
- @override
ClassEntity get jsNumberClass =>
_jsNumberClass ??= _findInterceptorsClass('JSNumber');
- ClassEntity _jsIntClass;
- @override
ClassEntity get jsIntClass => _jsIntClass ??= _findInterceptorsClass('JSInt');
- ClassEntity _jsNumNotIntClass;
- @override
ClassEntity get jsNumNotIntClass =>
_jsNumNotIntClass ??= _findInterceptorsClass('JSNumNotInt');
- ClassEntity _jsNullClass;
- @override
ClassEntity get jsNullClass =>
_jsNullClass ??= _findInterceptorsClass('JSNull');
- ClassEntity _jsBoolClass;
- @override
ClassEntity get jsBoolClass =>
_jsBoolClass ??= _findInterceptorsClass('JSBool');
- ClassEntity _jsPlainJavaScriptObjectClass;
- @override
ClassEntity get jsPlainJavaScriptObjectClass =>
_jsPlainJavaScriptObjectClass ??=
_findInterceptorsClass('PlainJavaScriptObject');
- ClassEntity _jsUnknownJavaScriptObjectClass;
- @override
ClassEntity get jsUnknownJavaScriptObjectClass =>
_jsUnknownJavaScriptObjectClass ??=
_findInterceptorsClass('UnknownJavaScriptObject');
- ClassEntity _jsJavaScriptFunctionClass;
- @override
ClassEntity get jsJavaScriptFunctionClass => _jsJavaScriptFunctionClass ??=
_findInterceptorsClass('JavaScriptFunction');
- @override
InterfaceType get jsJavaScriptFunctionType =>
_getRawType(jsJavaScriptFunctionClass);
- ClassEntity _jsLegacyJavaScriptObjectClass;
- @override
ClassEntity get jsLegacyJavaScriptObjectClass =>
_jsLegacyJavaScriptObjectClass ??=
_findInterceptorsClass('LegacyJavaScriptObject');
- ClassEntity _jsJavaScriptObjectClass;
- @override
ClassEntity get jsJavaScriptObjectClass =>
_jsJavaScriptObjectClass ??= _findInterceptorsClass('JavaScriptObject');
- ClassEntity _jsIndexableClass;
- @override
ClassEntity get jsIndexableClass =>
_jsIndexableClass ??= _findInterceptorsClass('JSIndexable');
- ClassEntity _jsMutableIndexableClass;
- @override
ClassEntity get jsMutableIndexableClass =>
_jsMutableIndexableClass ??= _findInterceptorsClass('JSMutableIndexable');
- ClassEntity _jsMutableArrayClass;
- @override
ClassEntity get jsMutableArrayClass =>
_jsMutableArrayClass ??= _findInterceptorsClass('JSMutableArray');
- ClassEntity _jsFixedArrayClass;
- @override
ClassEntity get jsFixedArrayClass =>
_jsFixedArrayClass ??= _findInterceptorsClass('JSFixedArray');
- ClassEntity _jsExtendableArrayClass;
- @override
ClassEntity get jsExtendableArrayClass =>
_jsExtendableArrayClass ??= _findInterceptorsClass('JSExtendableArray');
- ClassEntity _jsUnmodifiableArrayClass;
- @override
ClassEntity get jsUnmodifiableArrayClass => _jsUnmodifiableArrayClass ??=
_findInterceptorsClass('JSUnmodifiableArray');
- ClassEntity _jsPositiveIntClass;
- @override
ClassEntity get jsPositiveIntClass =>
_jsPositiveIntClass ??= _findInterceptorsClass('JSPositiveInt');
- ClassEntity _jsUInt32Class;
- @override
ClassEntity get jsUInt32Class =>
_jsUInt32Class ??= _findInterceptorsClass('JSUInt32');
- ClassEntity _jsUInt31Class;
- @override
ClassEntity get jsUInt31Class =>
_jsUInt31Class ??= _findInterceptorsClass('JSUInt31');
- @override
+ /// Returns `true` member is the 'findIndexForNativeSubclassType' method
+ /// declared in `dart:_interceptors`.
bool isFindIndexForNativeSubclassType(MemberEntity member) {
return member.name == 'findIndexForNativeSubclassType' &&
member.isTopLevel &&
member.library == interceptorsLibrary;
}
- FunctionEntity _getNativeInterceptorMethod;
- @override
FunctionEntity get getNativeInterceptorMethod =>
_getNativeInterceptorMethod ??=
_findInterceptorsFunction('getNativeInterceptor');
- @override
- bool appliesToJsIndexableLength(Selector selector) {
- return selector.name == 'length' && (selector.isGetter || selector.isCall);
- }
-
- ConstructorEntity _jsArrayTypedConstructor;
- @override
ConstructorEntity get jsArrayTypedConstructor =>
_jsArrayTypedConstructor ??= _findConstructor(jsArrayClass, 'typed');
- FunctionEntity _jsArrayRemoveLast;
- @override
- FunctionEntity get jsArrayRemoveLast =>
- _jsArrayRemoveLast ??= _findClassMember(jsArrayClass, 'removeLast');
-
- FunctionEntity _jsArrayAdd;
- @override
- FunctionEntity get jsArrayAdd =>
- _jsArrayAdd ??= _findClassMember(jsArrayClass, 'add');
-
- bool _isJsStringClass(ClassEntity cls) {
- return cls.name == 'JSString' && cls.library == interceptorsLibrary;
- }
-
- @override
- bool isJsStringSplit(MemberEntity member) {
- return member.name == 'split' &&
- member.isInstanceMember &&
- _isJsStringClass(member.enclosingClass);
- }
-
- @override
- bool appliesToJsStringSplit(Selector selector, AbstractValue receiver,
- AbstractValueDomain abstractValueDomain) {
- if (_jsStringSplit == null) {
- ClassEntity cls =
- _findClass(interceptorsLibrary, 'JSString', required: false);
- if (cls == null) return false;
- _jsStringSplit = _findClassMember(cls, 'split', required: false);
- if (_jsStringSplit == null) return false;
- }
- return selector.applies(_jsStringSplit) &&
- (receiver == null ||
- abstractValueDomain
- .isTargetingMember(receiver, jsStringSplit, selector.memberName)
- .isPotentiallyTrue);
- }
-
- FunctionEntity _jsStringSplit;
- @override
- FunctionEntity get jsStringSplit =>
- _jsStringSplit ??= _findClassMember(jsStringClass, 'split');
-
- FunctionEntity _jsStringToString;
- @override
- FunctionEntity get jsStringToString =>
- _jsStringToString ??= _findClassMember(jsStringClass, 'toString');
-
- FunctionEntity _jsStringOperatorAdd;
- @override
- FunctionEntity get jsStringOperatorAdd =>
- _jsStringOperatorAdd ??= _findClassMember(jsStringClass, '+');
-
- ClassEntity _jsConstClass;
- @override
- ClassEntity get jsConstClass =>
- _jsConstClass ??= _findClass(foreignLibrary, 'JS_CONST');
-
- // From dart:js
- FunctionEntity _jsAllowInterop1;
- @override
- FunctionEntity get jsAllowInterop1 => _jsAllowInterop1 ??=
- _findLibraryMember(dartJsLibrary, 'allowInterop', required: false);
-
- // From dart:_js_annotations
- FunctionEntity _jsAllowInterop2;
- @override
- FunctionEntity get jsAllowInterop2 => _jsAllowInterop2 ??= _findLibraryMember(
- dartJsAnnotationsLibrary, 'allowInterop',
- required: false);
-
- @override
- bool isJsAllowInterop(FunctionEntity function) {
- return function == jsAllowInterop1 || function == jsAllowInterop2;
- }
-
- // From package:js
- ClassEntity _jsAnnotationClass1;
- @override
- ClassEntity get jsAnnotationClass1 => _jsAnnotationClass1 ??=
- _findClass(packageJsLibrary, 'JS', required: false);
-
- // From dart:_js_annotations
- ClassEntity _jsAnnotationClass2;
- @override
- ClassEntity get jsAnnotationClass2 => _jsAnnotationClass2 ??=
- _findClass(dartJsAnnotationsLibrary, 'JS', required: false);
-
- @override
- bool isJsAnnotationClass(ClassEntity cls) {
- return cls == jsAnnotationClass1 || cls == jsAnnotationClass2;
- }
-
- // From dart:js
- ClassEntity _jsAnonymousClass1;
- @override
- ClassEntity get jsAnonymousClass1 => _jsAnonymousClass1 ??=
- _findClass(packageJsLibrary, '_Anonymous', required: false);
-
- // From dart:_js_annotations
- ClassEntity _jsAnonymousClass2;
- @override
- ClassEntity get jsAnonymousClass2 => _jsAnonymousClass2 ??=
- _findClass(dartJsAnnotationsLibrary, '_Anonymous', required: false);
-
- @override
- bool isJsAnonymousClass(ClassEntity cls) {
- return cls == jsAnonymousClass1 || cls == jsAnonymousClass2;
- }
-
- @override
+ // From dart:_js_helper
+ // TODO(johnniwinther): Avoid the need for this (from [CheckedModeHelper]).
FunctionEntity findHelperFunction(String name) => _findHelperFunction(name);
FunctionEntity _findHelperFunction(String name) =>
@@ -1549,186 +764,125 @@
FunctionEntity _findLateHelperFunction(String name) =>
_findLibraryMember(lateHelperLibrary, name);
- ClassEntity _closureClass;
- @override
ClassEntity get closureClass => _closureClass ??= _findHelperClass('Closure');
- ClassEntity _closureClass0Args;
- @override
ClassEntity get closureClass0Args =>
_closureClass0Args ??= _findHelperClass('Closure0Args');
- ClassEntity _closureClass2Args;
- @override
ClassEntity get closureClass2Args =>
_closureClass2Args ??= _findHelperClass('Closure2Args');
- ClassEntity _boundClosureClass;
- @override
ClassEntity get boundClosureClass =>
_boundClosureClass ??= _findHelperClass('BoundClosure');
- ClassEntity _typeLiteralClass;
- @override
ClassEntity get typeLiteralClass =>
_typeLiteralClass ??= _findRtiClass('_Type');
- ClassEntity _constMapLiteralClass;
- @override
ClassEntity get constMapLiteralClass =>
_constMapLiteralClass ??= _findHelperClass('ConstantMap');
// TODO(fishythefish): Implement a `ConstantSet` class and update the backend
// impacts + constant emitter accordingly.
- ClassEntity _constSetLiteralClass;
- @override
ClassEntity get constSetLiteralClass =>
_constSetLiteralClass ??= unmodifiableSetClass;
- ClassEntity _pragmaClass;
- @override
- ClassEntity get pragmaClass =>
- _pragmaClass ??= _findClass(coreLibrary, 'pragma');
-
- FieldEntity _pragmaClassNameField;
- @override
- FieldEntity get pragmaClassNameField =>
- _pragmaClassNameField ??= _findClassMember(pragmaClass, 'name');
-
- FieldEntity _pragmaClassOptionsField;
- @override
- FieldEntity get pragmaClassOptionsField =>
- _pragmaClassOptionsField ??= _findClassMember(pragmaClass, 'options');
-
- ClassEntity _jsInvocationMirrorClass;
- @override
ClassEntity get jsInvocationMirrorClass =>
_jsInvocationMirrorClass ??= _findHelperClass('JSInvocationMirror');
- ClassEntity _requiredSentinelClass;
- @override
ClassEntity get requiredSentinelClass =>
_requiredSentinelClass ??= _findHelperClass('_Required');
- @override
+
InterfaceType get requiredSentinelType => _getRawType(requiredSentinelClass);
- MemberEntity _invocationTypeArgumentGetter;
- @override
MemberEntity get invocationTypeArgumentGetter =>
_invocationTypeArgumentGetter ??=
_findClassMember(jsInvocationMirrorClass, 'typeArguments');
- ClassEntity _jsIndexingBehaviorInterface;
- @override
+ /// Interface used to determine if an object has the JavaScript
+ /// indexing behavior. The interface is only visible to specific libraries.
ClassEntity get jsIndexingBehaviorInterface =>
_jsIndexingBehaviorInterface ??=
_findHelperClass('JavaScriptIndexingBehavior');
- @override
ClassEntity get stackTraceHelperClass => _findHelperClass('_StackTrace');
- @override
ClassEntity get constantMapClass =>
_findHelperClass(constant_system.JavaScriptMapConstant.DART_CLASS);
- @override
+
ClassEntity get constantStringMapClass =>
_findHelperClass(constant_system.JavaScriptMapConstant.DART_STRING_CLASS);
- @override
+
ClassEntity get generalConstantMapClass => _findHelperClass(
constant_system.JavaScriptMapConstant.DART_GENERAL_CLASS);
- @override
ClassEntity get annotationCreatesClass => _findHelperClass('Creates');
- @override
ClassEntity get annotationReturnsClass => _findHelperClass('Returns');
- @override
ClassEntity get annotationJSNameClass => _findHelperClass('JSName');
- ClassEntity _nativeAnnotationClass;
- @override
+ /// The class for native annotations defined in dart:_js_helper.
ClassEntity get nativeAnnotationClass =>
_nativeAnnotationClass ??= _findHelperClass('Native');
- FunctionEntity _assertTest;
- @override
FunctionEntity get assertTest =>
_assertTest ??= _findHelperFunction('assertTest');
- FunctionEntity _assertThrow;
- @override
FunctionEntity get assertThrow =>
_assertThrow ??= _findHelperFunction('assertThrow');
- FunctionEntity _assertHelper;
- @override
FunctionEntity get assertHelper =>
_assertHelper ??= _findHelperFunction('assertHelper');
- FunctionEntity _assertUnreachableMethod;
- @override
FunctionEntity get assertUnreachableMethod =>
_assertUnreachableMethod ??= _findHelperFunction('assertUnreachable');
- FunctionEntity _getIsolateAffinityTagMarker;
- @override
+ /// Holds the method "getIsolateAffinityTag" when dart:_js_helper has been
+ /// loaded.
FunctionEntity get getIsolateAffinityTagMarker =>
_getIsolateAffinityTagMarker ??=
_findHelperFunction('getIsolateAffinityTag');
- FunctionEntity _requiresPreambleMarker;
- @override
+ /// Holds the method "requiresPreamble" in _js_helper.
FunctionEntity get requiresPreambleMarker =>
_requiresPreambleMarker ??= _findHelperFunction('requiresPreamble');
- FunctionEntity _rawStartupMetrics;
- @override
+ /// Holds the method "_rawStartupMetrics" in _js_helper.
FunctionEntity get rawStartupMetrics =>
_rawStartupMetrics ??= _findHelperFunction('rawStartupMetrics');
- @override
FunctionEntity get loadLibraryWrapper =>
_findHelperFunction("_loadLibraryWrapper");
- @override
FunctionEntity get loadDeferredLibrary =>
_findHelperFunction("loadDeferredLibrary");
- @override
FunctionEntity get boolConversionCheck =>
_findHelperFunction('boolConversionCheck');
- @override
FunctionEntity get traceHelper => _findHelperFunction('traceHelper');
- @override
FunctionEntity get closureFromTearOff =>
_findHelperFunction('closureFromTearOff');
- @override
FunctionEntity get isJsIndexable => _findHelperFunction('isJsIndexable');
- @override
FunctionEntity get throwIllegalArgumentException =>
_findHelperFunction('iae');
- @override
FunctionEntity get throwIndexOutOfRangeException =>
_findHelperFunction('ioore');
- @override
FunctionEntity get exceptionUnwrapper =>
_findHelperFunction('unwrapException');
- @override
FunctionEntity get throwUnsupportedError =>
_findHelperFunction('throwUnsupportedError');
- @override
FunctionEntity get throwTypeError => _findRtiFunction('throwTypeError');
- @override
+ /// Recognizes the `checkConcurrentModificationError` helper without needing
+ /// it to be resolved.
bool isCheckConcurrentModificationError(MemberEntity member) {
return member.name == 'checkConcurrentModificationError' &&
member.isFunction &&
@@ -1736,101 +890,52 @@
member.library == jsHelperLibrary;
}
- FunctionEntity _cachedCheckConcurrentModificationError;
- @override
FunctionEntity get checkConcurrentModificationError =>
_cachedCheckConcurrentModificationError ??=
_findHelperFunction('checkConcurrentModificationError');
- @override
FunctionEntity get throwConcurrentModificationError =>
_findHelperFunction('throwConcurrentModificationError');
- @override
- bool isCheckInt(MemberEntity member) {
- return member.isFunction &&
- member.isTopLevel &&
- member.library == jsHelperLibrary &&
- member.name == 'checkInt';
- }
-
- @override
- bool isCheckNum(MemberEntity member) {
- return member.isFunction &&
- member.isTopLevel &&
- member.library == jsHelperLibrary &&
- member.name == 'checkNum';
- }
-
- @override
- bool isCheckString(MemberEntity member) {
- return member.isFunction &&
- member.isTopLevel &&
- member.library == jsHelperLibrary &&
- member.name == 'checkString';
- }
-
- @override
FunctionEntity get stringInterpolationHelper => _findHelperFunction('S');
- @override
FunctionEntity get wrapExceptionHelper =>
_findHelperFunction('wrapException');
- @override
FunctionEntity get throwExpressionHelper =>
_findHelperFunction('throwExpression');
- @override
FunctionEntity get closureConverter =>
_findHelperFunction('convertDartClosureToJS');
- @override
FunctionEntity get traceFromException =>
_findHelperFunction('getTraceFromException');
- @override
FunctionEntity get checkDeferredIsLoaded =>
_findHelperFunction('checkDeferredIsLoaded');
- @override
FunctionEntity get throwNoSuchMethod =>
_findHelperFunction('throwNoSuchMethod');
- @override
FunctionEntity get createRuntimeType => _findRtiFunction('createRuntimeType');
- @override
FunctionEntity get fallThroughError =>
_findHelperFunction("getFallThroughError");
- @override
FunctionEntity get createInvocationMirror =>
_findHelperFunction('createInvocationMirror');
- @override
- bool isCreateInvocationMirrorHelper(MemberEntity member) {
- return member.isTopLevel &&
- member.name == '_createInvocationMirror' &&
- member.library == coreLibrary;
- }
-
- @override
FunctionEntity get createUnmangledInvocationMirror =>
_findHelperFunction('createUnmangledInvocationMirror');
- @override
FunctionEntity get cyclicThrowHelper =>
_findHelperFunction("throwCyclicInit");
- @override
FunctionEntity get defineProperty => _findHelperFunction('defineProperty');
- @override
FunctionEntity get throwLateFieldADI =>
_findLateHelperFunction('throwLateFieldADI');
- @override
bool isExtractTypeArguments(FunctionEntity member) {
return member.name == 'extractTypeArguments' &&
member.library == internalLibrary;
@@ -1847,26 +952,16 @@
}
}
- @override
ClassEntity getInstantiationClass(int typeArgumentCount) {
_checkTypeArgumentCount(typeArgumentCount);
return _findHelperClass('Instantiation$typeArgumentCount');
}
- @override
FunctionEntity getInstantiateFunction(int typeArgumentCount) {
_checkTypeArgumentCount(typeArgumentCount);
return _findHelperFunction('instantiate$typeArgumentCount');
}
- @override
- bool isInstantiationClass(ClassEntity cls) {
- return cls.library == _jsHelperLibrary &&
- cls.name != 'Instantiation' &&
- cls.name.startsWith('Instantiation');
- }
-
- @override
FunctionEntity get convertMainArgumentList =>
_findHelperFunction('convertMainArgumentList');
@@ -1877,259 +972,159 @@
FunctionEntity _findRtiFunction(String name) =>
_findLibraryMember(rtiLibrary, name);
- FunctionEntity _setArrayType;
- @override
FunctionEntity get setArrayType =>
_setArrayType ??= _findRtiFunction('_setArrayType');
- FunctionEntity _findType;
- @override
FunctionEntity get findType => _findType ??= _findRtiFunction('findType');
- FunctionEntity _instanceType;
- @override
FunctionEntity get instanceType =>
_instanceType ??= _findRtiFunction('instanceType');
- FunctionEntity _arrayInstanceType;
- @override
FunctionEntity get arrayInstanceType =>
_arrayInstanceType ??= _findRtiFunction('_arrayInstanceType');
- FunctionEntity _simpleInstanceType;
- @override
FunctionEntity get simpleInstanceType =>
_simpleInstanceType ??= _findRtiFunction('_instanceType');
- FunctionEntity _typeLiteralMaker;
- @override
FunctionEntity get typeLiteralMaker =>
_typeLiteralMaker ??= _findRtiFunction('typeLiteral');
- FunctionEntity _checkTypeBound;
- @override
FunctionEntity get checkTypeBound =>
_checkTypeBound ??= _findRtiFunction('checkTypeBound');
ClassEntity get _rtiImplClass => _findClass(rtiLibrary, 'Rti');
+
ClassEntity get _rtiUniverseClass => _findClass(rtiLibrary, '_Universe');
+
FieldEntity _findRtiClassField(String name) =>
_findClassMember(_rtiImplClass, name);
- FieldEntity _rtiAsField;
- @override
FieldEntity get rtiAsField => _rtiAsField ??= _findRtiClassField('_as');
- FieldEntity _rtiIsField;
- @override
FieldEntity get rtiIsField => _rtiIsField ??= _findRtiClassField('_is');
- FieldEntity _rtiRestField;
- @override
FieldEntity get rtiRestField => _rtiRestField ??= _findRtiClassField('_rest');
- FieldEntity _rtiPrecomputed1Field;
- @override
FieldEntity get rtiPrecomputed1Field =>
_rtiPrecomputed1Field ??= _findRtiClassField('_precomputed1');
- FunctionEntity _rtiEvalMethod;
- @override
FunctionEntity get rtiEvalMethod =>
_rtiEvalMethod ??= _findClassMember(_rtiImplClass, '_eval');
- FunctionEntity _rtiBindMethod;
- @override
FunctionEntity get rtiBindMethod =>
_rtiBindMethod ??= _findClassMember(_rtiImplClass, '_bind');
- FunctionEntity _rtiAddRulesMethod;
- @override
FunctionEntity get rtiAddRulesMethod =>
_rtiAddRulesMethod ??= _findClassMember(_rtiUniverseClass, 'addRules');
- FunctionEntity _rtiAddErasedTypesMethod;
- @override
FunctionEntity get rtiAddErasedTypesMethod => _rtiAddErasedTypesMethod ??=
_findClassMember(_rtiUniverseClass, 'addErasedTypes');
- FunctionEntity _rtiAddTypeParameterVariancesMethod;
- @override
FunctionEntity get rtiAddTypeParameterVariancesMethod =>
_rtiAddTypeParameterVariancesMethod ??=
_findClassMember(_rtiUniverseClass, 'addTypeParameterVariances');
- @override
FunctionEntity get installSpecializedIsTest =>
_findRtiFunction('_installSpecializedIsTest');
- @override
FunctionEntity get installSpecializedAsCheck =>
_findRtiFunction('_installSpecializedAsCheck');
- FunctionEntity _generalIsTestImplementation;
- @override
FunctionEntity get generalIsTestImplementation =>
_generalIsTestImplementation ??=
_findRtiFunction('_generalIsTestImplementation');
- FunctionEntity _generalNullableIsTestImplementation;
- @override
FunctionEntity get generalNullableIsTestImplementation =>
_generalNullableIsTestImplementation ??=
_findRtiFunction('_generalNullableIsTestImplementation');
- FunctionEntity _generalAsCheckImplementation;
- @override
FunctionEntity get generalAsCheckImplementation =>
_generalAsCheckImplementation ??=
_findRtiFunction('_generalAsCheckImplementation');
- FunctionEntity _generalNullableAsCheckImplementation;
- @override
FunctionEntity get generalNullableAsCheckImplementation =>
_generalNullableAsCheckImplementation ??=
_findRtiFunction('_generalNullableAsCheckImplementation');
- FunctionEntity _specializedIsObject;
- @override
FunctionEntity get specializedIsObject =>
_specializedIsObject ??= _findRtiFunction('_isObject');
- FunctionEntity _specializedAsObject;
- @override
FunctionEntity get specializedAsObject =>
_specializedAsObject ??= _findRtiFunction('_asObject');
- @override
FunctionEntity get specializedIsTop => _findRtiFunction('_isTop');
- @override
FunctionEntity get specializedAsTop => _findRtiFunction('_asTop');
- @override
FunctionEntity get specializedIsBool => _findRtiFunction('_isBool');
- @override
FunctionEntity get specializedAsBool => _findRtiFunction('_asBool');
- @override
FunctionEntity get specializedAsBoolLegacy => _findRtiFunction('_asBoolS');
- @override
FunctionEntity get specializedAsBoolNullable => _findRtiFunction('_asBoolQ');
- @override
FunctionEntity get specializedAsDouble => _findRtiFunction('_asDouble');
- @override
FunctionEntity get specializedAsDoubleLegacy =>
_findRtiFunction('_asDoubleS');
- @override
FunctionEntity get specializedAsDoubleNullable =>
_findRtiFunction('_asDoubleQ');
- @override
FunctionEntity get specializedIsInt => _findRtiFunction('_isInt');
- @override
FunctionEntity get specializedAsInt => _findRtiFunction('_asInt');
- @override
FunctionEntity get specializedAsIntLegacy => _findRtiFunction('_asIntS');
- @override
FunctionEntity get specializedAsIntNullable => _findRtiFunction('_asIntQ');
- @override
FunctionEntity get specializedIsNum => _findRtiFunction('_isNum');
- @override
FunctionEntity get specializedAsNum => _findRtiFunction('_asNum');
- @override
FunctionEntity get specializedAsNumLegacy => _findRtiFunction('_asNumS');
- @override
FunctionEntity get specializedAsNumNullable => _findRtiFunction('_asNumQ');
- @override
FunctionEntity get specializedIsString => _findRtiFunction('_isString');
- @override
FunctionEntity get specializedAsString => _findRtiFunction('_asString');
- @override
FunctionEntity get specializedAsStringLegacy =>
_findRtiFunction('_asStringS');
- @override
FunctionEntity get specializedAsStringNullable =>
_findRtiFunction('_asStringQ');
- @override
FunctionEntity get instantiatedGenericFunctionTypeNewRti =>
_findRtiFunction('instantiatedGenericFunctionType');
- @override
FunctionEntity get closureFunctionType =>
_findRtiFunction('closureFunctionType');
// From dart:_internal
- ClassEntity _symbolImplementationClass;
- @override
ClassEntity get symbolImplementationClass =>
_symbolImplementationClass ??= _findClass(internalLibrary, 'Symbol');
- ClassEntity _externalNameClass;
- @override
+ /// Used to annotate items that have the keyword "native".
ClassEntity get externalNameClass =>
_externalNameClass ??= _findClass(internalLibrary, 'ExternalName');
- @override
+
InterfaceType get externalNameType => _getRawType(externalNameClass);
- /// Returns the field that holds the internal name in the implementation class
- /// for `Symbol`.
- FieldEntity _symbolImplementationField;
- FieldEntity get symbolImplementationField => _symbolImplementationField ??=
- _env.lookupLocalClassMember(symbolImplementationClass, '_name',
- required: true);
-
- // From dart:_native_typed_data
-
- ClassEntity _typedArrayOfIntClass;
- @override
- ClassEntity get typedArrayOfIntClass => _typedArrayOfIntClass ??= _findClass(
- _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
- 'NativeTypedArrayOfInt');
-
- ClassEntity _typedArrayOfDoubleClass;
- @override
- ClassEntity get typedArrayOfDoubleClass =>
- _typedArrayOfDoubleClass ??= _findClass(
- _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
- 'NativeTypedArrayOfDouble');
-
// From dart:_js_embedded_names
- ClassEntity _jsGetNameEnum;
- @override
ClassEntity get jsGetNameEnum => _jsGetNameEnum ??= _findClass(
_env.lookupLibrary(Uris.dart__js_embedded_names, required: true),
'JsGetName');
- ClassEntity _jsBuiltinEnum;
- @override
- ClassEntity get jsBuiltinEnum => _jsBuiltinEnum ??= _findClass(
- _env.lookupLibrary(Uris.dart__js_embedded_names, required: true),
- 'JsBuiltin');
-
- @override
- bool isForeign(MemberEntity element) => element.library == foreignLibrary;
-
- @override
+ /// Returns `true` if [member] is a "foreign helper", that is, a member whose
+ /// semantics is defined synthetically and not through Dart code.
+ ///
+ /// Most foreign helpers are located in the `dart:_foreign_helper` library.
bool isForeignHelper(MemberEntity member) {
return member.library == foreignLibrary ||
isCreateInvocationMirrorHelper(member);
@@ -2138,37 +1133,30 @@
bool _isTopLevelFunctionNamed(String name, MemberEntity member) =>
member.name == name && member.isFunction && member.isTopLevel;
- @override
+ /// Returns `true` if [member] is the `createJsSentinel` function defined in
+ /// dart:_foreign_helper.
bool isCreateJsSentinel(MemberEntity member) =>
member.library == foreignLibrary &&
_isTopLevelFunctionNamed('createJsSentinel', member);
- @override
+ /// Returns `true` if [member] is the `isJsSentinel` function defined in
+ /// dart:_foreign_helper.
bool isIsJsSentinel(MemberEntity member) =>
member.library == foreignLibrary &&
_isTopLevelFunctionNamed('isJsSentinel', member);
- @override
+ /// Returns `true` if [member] is the `_lateReadCheck` function defined in
+ /// dart:_internal.
bool isLateReadCheck(MemberEntity member) =>
member.library == lateHelperLibrary &&
_isTopLevelFunctionNamed('_lateReadCheck', member);
- @override
+ /// Returns `true` if [member] is the `createSentinel` function defined in
+ /// dart:_internal.
bool isCreateSentinel(MemberEntity member) =>
member.library == internalLibrary &&
_isTopLevelFunctionNamed('createSentinel', member);
- @override
- bool operatorEqHandlesNullArgument(FunctionEntity function) {
- assert(function.name == '==',
- failedAt(function, "Unexpected function $function."));
- ClassEntity cls = function.enclosingClass;
- return cls == objectClass ||
- cls == jsInterceptorClass ||
- cls == jsNullClass;
- }
-
- @override
ClassEntity getDefaultSuperclass(
ClassEntity cls, NativeBasicData nativeBasicData) {
if (nativeBasicData.isJsInteropClass(cls)) {
@@ -2179,6 +1167,241 @@
? jsInterceptorClass
: objectClass;
}
+
+ // From package:js
+ FunctionEntity get jsAllowInterop1 => _jsAllowInterop1 ??=
+ _findLibraryMember(dartJsLibrary, 'allowInterop', required: false);
+
+ // From dart:_js_annotations;
+ FunctionEntity get jsAllowInterop2 => _jsAllowInterop2 ??= _findLibraryMember(
+ dartJsAnnotationsLibrary, 'allowInterop',
+ required: false);
+
+ /// Returns `true` if [function] is `allowInterop`.
+ ///
+ /// This function can come from either `package:js` or `dart:_js_annotations`.
+ bool isJsAllowInterop(FunctionEntity function) {
+ return function == jsAllowInterop1 || function == jsAllowInterop2;
+ }
+
+ bool isCreateInvocationMirrorHelper(MemberEntity member) {
+ return member.isTopLevel &&
+ member.name == '_createInvocationMirror' &&
+ member.library == coreLibrary;
+ }
+}
+
+class KCommonElements extends CommonElements {
+ ClassEntity _jsAnnotationClass1;
+ ClassEntity _jsAnonymousClass1;
+ ClassEntity _jsAnnotationClass2;
+ ClassEntity _jsAnonymousClass2;
+ ClassEntity _pragmaClass;
+ FieldEntity _pragmaClassNameField;
+ FieldEntity _pragmaClassOptionsField;
+
+ KCommonElements(DartTypes dartTypes, ElementEnvironment env)
+ : super(dartTypes, env);
+
+ // From package:js
+
+ ClassEntity get jsAnnotationClass1 => _jsAnnotationClass1 ??=
+ _findClass(packageJsLibrary, 'JS', required: false);
+
+ ClassEntity get jsAnonymousClass1 => _jsAnonymousClass1 ??=
+ _findClass(packageJsLibrary, '_Anonymous', required: false);
+
+ // From dart:_js_annotations
+
+ ClassEntity get jsAnnotationClass2 => _jsAnnotationClass2 ??=
+ _findClass(dartJsAnnotationsLibrary, 'JS', required: false);
+
+ ClassEntity get jsAnonymousClass2 => _jsAnonymousClass2 ??=
+ _findClass(dartJsAnnotationsLibrary, '_Anonymous', required: false);
+
+ /// Returns `true` if [cls] is a @JS() annotation.
+ ///
+ /// The class can come from either `package:js` or `dart:_js_annotations`.
+ bool isJsAnnotationClass(ClassEntity cls) {
+ return cls == jsAnnotationClass1 || cls == jsAnnotationClass2;
+ }
+
+ /// Returns `true` if [cls] is an @anonymous annotation.
+ ///
+ /// The class can come from either `package:js` or `dart:_js_annotations`.
+ bool isJsAnonymousClass(ClassEntity cls) {
+ return cls == jsAnonymousClass1 || cls == jsAnonymousClass2;
+ }
+
+ ClassEntity get pragmaClass =>
+ _pragmaClass ??= _findClass(coreLibrary, 'pragma');
+
+ FieldEntity get pragmaClassNameField =>
+ _pragmaClassNameField ??= _findClassMember(pragmaClass, 'name');
+
+ FieldEntity get pragmaClassOptionsField =>
+ _pragmaClassOptionsField ??= _findClassMember(pragmaClass, 'options');
+}
+
+class JCommonElements extends CommonElements {
+ FunctionEntity _jsArrayRemoveLast;
+ FunctionEntity _jsArrayAdd;
+ FunctionEntity _jsStringSplit;
+ FunctionEntity _jsStringToString;
+ FunctionEntity _jsStringOperatorAdd;
+ ClassEntity _jsConstClass;
+ ClassEntity _typedArrayOfIntClass;
+ ClassEntity _typedArrayOfDoubleClass;
+ ClassEntity _jsBuiltinEnum;
+
+ JCommonElements(DartTypes dartTypes, ElementEnvironment env)
+ : super(dartTypes, env);
+
+ /// Returns `true` if [element] is the unnamed constructor of `List`.
+ ///
+ /// This will not resolve the constructor if it hasn't been seen yet during
+ /// compilation.
+ bool isUnnamedListConstructor(ConstructorEntity element) =>
+ (element.name == '' && element.enclosingClass == listClass) ||
+ (element.name == 'list' && element.enclosingClass == jsArrayClass);
+
+ /// Returns `true` if [element] is the named constructor of `List`,
+ /// e.g. `List.of`.
+ ///
+ /// This will not resolve the constructor if it hasn't been seen yet during
+ /// compilation.
+ bool isNamedListConstructor(String name, ConstructorEntity element) =>
+ element.name == name && element.enclosingClass == listClass;
+
+ /// Returns `true` if [element] is the named constructor of `JSArray`,
+ /// e.g. `JSArray.fixed`.
+ ///
+ /// This will not resolve the constructor if it hasn't been seen yet during
+ /// compilation.
+ bool isNamedJSArrayConstructor(String name, ConstructorEntity element) =>
+ element.name == name && element.enclosingClass == jsArrayClass;
+
+ bool isDefaultEqualityImplementation(MemberEntity element) {
+ assert(element.name == '==');
+ ClassEntity classElement = element.enclosingClass;
+ return classElement == objectClass ||
+ classElement == jsInterceptorClass ||
+ classElement == jsNullClass;
+ }
+
+ /// Returns `true` if [selector] applies to `JSIndexable.length`.
+ bool appliesToJsIndexableLength(Selector selector) {
+ return selector.name == 'length' && (selector.isGetter || selector.isCall);
+ }
+
+ FunctionEntity get jsArrayRemoveLast =>
+ _jsArrayRemoveLast ??= _findClassMember(jsArrayClass, 'removeLast');
+
+ FunctionEntity get jsArrayAdd =>
+ _jsArrayAdd ??= _findClassMember(jsArrayClass, 'add');
+
+ bool _isJsStringClass(ClassEntity cls) {
+ return cls.name == 'JSString' && cls.library == interceptorsLibrary;
+ }
+
+ bool isJsStringSplit(MemberEntity member) {
+ return member.name == 'split' &&
+ member.isInstanceMember &&
+ _isJsStringClass(member.enclosingClass);
+ }
+
+ /// Returns `true` if [selector] applies to `JSString.split` on [receiver]
+ /// in the given [world].
+ ///
+ /// Returns `false` if `JSString.split` is not available.
+ bool appliesToJsStringSplit(Selector selector, AbstractValue receiver,
+ AbstractValueDomain abstractValueDomain) {
+ if (_jsStringSplit == null) {
+ ClassEntity cls =
+ _findClass(interceptorsLibrary, 'JSString', required: false);
+ if (cls == null) return false;
+ _jsStringSplit = _findClassMember(cls, 'split', required: false);
+ if (_jsStringSplit == null) return false;
+ }
+ return selector.applies(_jsStringSplit) &&
+ (receiver == null ||
+ abstractValueDomain
+ .isTargetingMember(receiver, jsStringSplit, selector.memberName)
+ .isPotentiallyTrue);
+ }
+
+ FunctionEntity get jsStringSplit =>
+ _jsStringSplit ??= _findClassMember(jsStringClass, 'split');
+
+ FunctionEntity get jsStringToString =>
+ _jsStringToString ??= _findClassMember(jsStringClass, 'toString');
+
+ FunctionEntity get jsStringOperatorAdd =>
+ _jsStringOperatorAdd ??= _findClassMember(jsStringClass, '+');
+
+ ClassEntity get jsConstClass =>
+ _jsConstClass ??= _findClass(foreignLibrary, 'JS_CONST');
+
+ /// Return `true` if [member] is the 'checkInt' function defined in
+ /// dart:_js_helpers.
+ bool isCheckInt(MemberEntity member) {
+ return member.isFunction &&
+ member.isTopLevel &&
+ member.library == jsHelperLibrary &&
+ member.name == 'checkInt';
+ }
+
+ /// Return `true` if [member] is the 'checkNum' function defined in
+ /// dart:_js_helpers.
+ bool isCheckNum(MemberEntity member) {
+ return member.isFunction &&
+ member.isTopLevel &&
+ member.library == jsHelperLibrary &&
+ member.name == 'checkNum';
+ }
+
+ /// Return `true` if [member] is the 'checkString' function defined in
+ /// dart:_js_helpers.
+ bool isCheckString(MemberEntity member) {
+ return member.isFunction &&
+ member.isTopLevel &&
+ member.library == jsHelperLibrary &&
+ member.name == 'checkString';
+ }
+
+ bool isInstantiationClass(ClassEntity cls) {
+ return cls.library == _jsHelperLibrary &&
+ cls.name != 'Instantiation' &&
+ cls.name.startsWith('Instantiation');
+ }
+
+ // From dart:_native_typed_data
+
+ ClassEntity get typedArrayOfIntClass => _typedArrayOfIntClass ??= _findClass(
+ _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
+ 'NativeTypedArrayOfInt');
+
+ ClassEntity get typedArrayOfDoubleClass =>
+ _typedArrayOfDoubleClass ??= _findClass(
+ _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
+ 'NativeTypedArrayOfDouble');
+
+ ClassEntity get jsBuiltinEnum => _jsBuiltinEnum ??= _findClass(
+ _env.lookupLibrary(Uris.dart__js_embedded_names, required: true),
+ 'JsBuiltin');
+
+ bool isForeign(MemberEntity element) => element.library == foreignLibrary;
+
+ /// Returns `true` if the implementation of the 'operator ==' [function] is
+ /// known to handle `null` as argument.
+ bool operatorEqHandlesNullArgument(FunctionEntity function) {
+ assert(function.name == '==',
+ failedAt(function, "Unexpected function $function."));
+ ClassEntity cls = function.enclosingClass;
+ return cls == objectClass ||
+ cls == jsInterceptorClass ||
+ cls == jsNullClass;
+ }
}
/// Interface for accessing libraries, classes and members.
@@ -2378,12 +1601,6 @@
/// Returns the imports seen in [library]
Iterable<ImportEntity> getImports(LibraryEntity library);
- /// Returns the metadata constants declared on [library].
- Iterable<ConstantValue> getLibraryMetadata(LibraryEntity library);
-
- /// Returns the metadata constants declared on [cls].
- Iterable<ConstantValue> getClassMetadata(ClassEntity cls);
-
/// Returns the metadata constants declared on [member].
Iterable<ConstantValue> getMemberMetadata(MemberEntity member,
{bool includeParameterMetadata = false});
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 8e1bf87..9ca6a7c 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -76,7 +76,7 @@
@override
final DiagnosticReporter reporter;
final Environment _environment;
- CommonElementsImpl _commonElements;
+ JCommonElements _commonElements;
JsElementEnvironment _elementEnvironment;
DartTypeConverter _typeConverter;
KernelDartTypes _types;
@@ -137,7 +137,7 @@
_elementEnvironment = JsElementEnvironment(this);
_typeConverter = DartTypeConverter(this);
_types = KernelDartTypes(this, options);
- _commonElements = CommonElementsImpl(_types, _elementEnvironment);
+ _commonElements = JCommonElements(_types, _elementEnvironment);
_constantValuefier = ConstantValuefier(this);
programEnv = _elementMap.env.convert();
@@ -297,7 +297,7 @@
_elementEnvironment = JsElementEnvironment(this);
_typeConverter = DartTypeConverter(this);
_types = KernelDartTypes(this, options);
- _commonElements = CommonElementsImpl(_types, _elementEnvironment);
+ _commonElements = JCommonElements(_types, _elementEnvironment);
_constantValuefier = ConstantValuefier(this);
source.registerComponentLookup(ComponentLookup(component));
@@ -510,7 +510,7 @@
JsElementEnvironment get elementEnvironment => _elementEnvironment;
@override
- CommonElementsImpl get commonElements => _commonElements;
+ JCommonElements get commonElements => _commonElements;
FunctionEntity get _mainFunction {
return programEnv.mainMethod != null
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 2d8e7b6..7bd67d0 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -65,7 +65,7 @@
@override
final DiagnosticReporter reporter;
final Environment _environment;
- CommonElementsImpl _commonElements;
+ KCommonElements _commonElements;
KernelElementEnvironment _elementEnvironment;
DartTypeConverter _typeConverter;
KernelDartTypes _types;
@@ -117,7 +117,7 @@
_elementEnvironment = KernelElementEnvironment(this);
_typeConverter = DartTypeConverter(this);
_types = KernelDartTypes(this, options);
- _commonElements = CommonElementsImpl(_types, _elementEnvironment);
+ _commonElements = KCommonElements(_types, _elementEnvironment);
_constantValuefier = ConstantValuefier(this);
}
@@ -128,7 +128,7 @@
KernelElementEnvironment get elementEnvironment => _elementEnvironment;
@override
- CommonElementsImpl get commonElements => _commonElements;
+ KCommonElements get commonElements => _commonElements;
FunctionEntity get _mainFunction {
return env.mainMethod != null ? getMethodInternal(env.mainMethod) : null;
@@ -1874,13 +1874,6 @@
}
@override
- Iterable<ConstantValue> getLibraryMetadata(covariant IndexedLibrary library) {
- assert(elementMap.checkFamily(library));
- KLibraryData libraryData = elementMap.libraries.getData(library);
- return libraryData.getMetadata(elementMap);
- }
-
- @override
Iterable<ImportEntity> getImports(covariant IndexedLibrary library) {
assert(elementMap.checkFamily(library));
KLibraryData libraryData = elementMap.libraries.getData(library);
@@ -1888,13 +1881,6 @@
}
@override
- Iterable<ConstantValue> getClassMetadata(covariant IndexedClass cls) {
- assert(elementMap.checkFamily(cls));
- KClassData classData = elementMap.classes.getData(cls);
- return classData.getMetadata(elementMap);
- }
-
- @override
Iterable<ConstantValue> getMemberMetadata(covariant IndexedMember member,
{bool includeParameterMetadata = false}) {
// TODO(redemption): Support includeParameterMetadata.
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index 9df3e23..2d4c60f 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -216,7 +216,7 @@
impactBuilder.registerFeature(Feature.SYNC_STAR);
impactBuilder.registerStaticUse(StaticUse.staticInvoke(
commonElements.syncStarIterableFactory,
- const CallStructure.unnamed(1, 1),
+ CallStructure.unnamed(1, 1),
<DartType>[elementMap.getDartType(elementType)]));
}
@@ -225,7 +225,7 @@
impactBuilder.registerFeature(Feature.ASYNC);
impactBuilder.registerStaticUse(StaticUse.staticInvoke(
commonElements.asyncAwaitCompleterFactory,
- const CallStructure.unnamed(0, 1),
+ CallStructure.unnamed(0, 1),
<DartType>[elementMap.getDartType(elementType)]));
}
@@ -234,7 +234,7 @@
impactBuilder.registerFeature(Feature.ASYNC_STAR);
impactBuilder.registerStaticUse(StaticUse.staticInvoke(
commonElements.asyncStarStreamControllerFactory,
- const CallStructure.unnamed(1, 1),
+ CallStructure.unnamed(1, 1),
<DartType>[elementMap.getDartType(elementType)]));
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 37d2d3e..139b3a2 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -2391,15 +2391,34 @@
@override
void visitAsExpression(ir.AsExpression node) {
- ir.Expression operand = node.operand;
+ // Recognize these special cases, where expression e has static type `T?`:
+ //
+ // e as T
+ // (e as dynamic) as T
+ //
+ // These patterns can only fail if `e` results in a `null` value. The
+ // second pattern occurs when `e as dynamic` is used get an implicit
+ // downcast in order to make use of the different policies for explicit and
+ // implicit downcasts.
+ //
+ // The pattern match is syntactic which ensures the type bindings are
+ // consistent, i.e. from the same instance of a type variable scope.
+ ir.Expression operand = _skipCastsToDynamic(node.operand);
operand.accept(this);
+ bool isNullRemovalPattern = false;
+
StaticType operandType = _getStaticType(operand);
DartType type = _elementMap.getDartType(node.type);
- if (!node.isCovarianceCheck &&
- _elementMap.types.isSubtype(operandType.type, type)) {
- // Skip unneeded casts.
- return;
+ if (!node.isCovarianceCheck) {
+ if (_elementMap.types.isSubtype(operandType.type, type)) {
+ // Skip unneeded casts.
+ return;
+ }
+ if (_elementMap.types
+ .isSubtype(operandType.type, _elementMap.types.nullableType(type))) {
+ isNullRemovalPattern = true;
+ }
}
SourceInformation sourceInformation =
@@ -2420,7 +2439,12 @@
.getExplicitCastCheckPolicy(_currentFrame.member);
}
- if (policy.isEmitted) {
+ if (!policy.isEmitted) {
+ stack.add(expressionInstruction);
+ return;
+ }
+
+ void generateCheck() {
HInstruction converted = _typeBuilder.buildAsCheck(
expressionInstruction, localsHandler.substInContext(type),
isTypeError: node.isTypeError, sourceInformation: sourceInformation);
@@ -2428,9 +2452,34 @@
add(converted);
}
stack.add(converted);
- } else {
- stack.add(expressionInstruction);
}
+
+ if (isNullRemovalPattern) {
+ // Generate a conditional to test only `null` values:
+ //
+ // temp = e;
+ // temp == null ? temp as T : temp
+ SsaBranchBuilder(this).handleConditional(
+ () {
+ push(HIdentity(
+ expressionInstruction,
+ graph.addConstantNull(closedWorld),
+ _abstractValueDomain.boolType));
+ },
+ generateCheck,
+ () {
+ stack.add(expressionInstruction);
+ });
+ } else {
+ generateCheck();
+ }
+ }
+
+ static ir.Expression _skipCastsToDynamic(ir.Expression node) {
+ if (node is ir.AsExpression && node.type is ir.DynamicType) {
+ return _skipCastsToDynamic(node.operand);
+ }
+ return node;
}
@override
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index 77182b9..4986815 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -220,7 +220,7 @@
registry.registerStaticUse(StaticUse.staticInvoke(
completerFactory,
- const CallStructure.unnamed(0, 1),
+ CallStructure.unnamed(0, 1),
[elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
return rewriter;
@@ -255,7 +255,7 @@
registry.registerStaticUse(StaticUse.staticInvoke(
commonElements.syncStarIterableFactory,
- const CallStructure.unnamed(1, 1),
+ CallStructure.unnamed(1, 1),
[elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
return rewriter;
@@ -293,7 +293,7 @@
registry.registerStaticUse(StaticUse.staticInvoke(
commonElements.asyncStarStreamControllerFactory,
- const CallStructure.unnamed(1, 1),
+ CallStructure.unnamed(1, 1),
[elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
return rewriter;
diff --git a/pkg/compiler/lib/src/universe/call_structure.dart b/pkg/compiler/lib/src/universe/call_structure.dart
index 234a3a9..1dc8cdd 100644
--- a/pkg/compiler/lib/src/universe/call_structure.dart
+++ b/pkg/compiler/lib/src/universe/call_structure.dart
@@ -11,7 +11,12 @@
import 'selector.dart' show Selector;
/// The structure of the arguments at a call-site.
-// TODO(johnniwinther): Should these be cached?
+///
+/// A call-site passes some number of arguments: some positional arguments
+/// followed by some named arguments. There may also be type arguments.
+///
+/// A CallStructure is unmodifiable.
+
// TODO(johnniwinther): Should isGetter/isSetter be part of the call structure
// instead of the selector?
class CallStructure {
@@ -19,11 +24,23 @@
/// data stream.
static const String tag = 'call-structure';
- static const CallStructure NO_ARGS = CallStructure.unnamed(0);
- static const CallStructure ONE_ARG = CallStructure.unnamed(1);
- static const CallStructure TWO_ARGS = CallStructure.unnamed(2);
- static const CallStructure THREE_ARGS = CallStructure.unnamed(3);
- static const CallStructure FOUR_ARGS = CallStructure.unnamed(4);
+ static const CallStructure NO_ARGS = CallStructure._(0);
+ static const CallStructure ONE_ARG = CallStructure._(1);
+ static const CallStructure TWO_ARGS = CallStructure._(2);
+
+ static const List<List<CallStructure>> _common = [
+ [NO_ARGS, CallStructure._(0, 1), CallStructure._(0, 2)],
+ [ONE_ARG, CallStructure._(1, 1), CallStructure._(1, 2)],
+ [TWO_ARGS, CallStructure._(2, 1), CallStructure._(2, 2)],
+ [CallStructure._(3), CallStructure._(3, 1), CallStructure._(3, 2)],
+ [CallStructure._(4), CallStructure._(4, 1), CallStructure._(4, 2)],
+ [CallStructure._(5), CallStructure._(5, 1), CallStructure._(5, 2)],
+ [CallStructure._(6)],
+ [CallStructure._(7)],
+ [CallStructure._(8)],
+ [CallStructure._(9)],
+ [CallStructure._(10)],
+ ];
/// The number of type arguments of the call.
final int typeArgumentCount;
@@ -37,14 +54,31 @@
/// The number of positional argument of the call.
int get positionalArgumentCount => argumentCount;
- const CallStructure.unnamed(this.argumentCount, [this.typeArgumentCount = 0]);
+ const CallStructure._(this.argumentCount, [this.typeArgumentCount = 0]);
+
+ factory CallStructure.unnamed(int argumentCount,
+ [int typeArgumentCount = 0]) {
+ // This simple canonicalization of common call structures greatly reduces
+ // the number of allocations of CallStructure objects.
+ if (argumentCount < _common.length) {
+ final row = _common[argumentCount];
+ if (typeArgumentCount < row.length) {
+ final result = row[typeArgumentCount];
+ assert(result.argumentCount == argumentCount &&
+ result.typeArgumentCount == typeArgumentCount);
+ return result;
+ }
+ }
+ return CallStructure._(argumentCount, typeArgumentCount);
+ }
factory CallStructure(int argumentCount,
[List<String> namedArguments, int typeArgumentCount = 0]) {
if (namedArguments == null || namedArguments.isEmpty) {
return CallStructure.unnamed(argumentCount, typeArgumentCount);
}
- return NamedCallStructure(argumentCount, namedArguments, typeArgumentCount);
+ return _NamedCallStructure(
+ argumentCount, namedArguments, typeArgumentCount, null);
}
/// Deserializes a [CallStructure] object from [source].
@@ -127,7 +161,7 @@
return this.argumentCount == other.argumentCount &&
this.namedArgumentCount == other.namedArgumentCount &&
this.typeArgumentCount == other.typeArgumentCount &&
- sameNames(this.namedArguments, other.namedArguments);
+ _sameNames(this.namedArguments, other.namedArguments);
}
// TODO(johnniwinther): Cache hash code?
@@ -193,7 +227,8 @@
}
}
- static bool sameNames(List<String> first, List<String> second) {
+ static bool _sameNames(List<String> first, List<String> second) {
+ assert(first.length == second.length);
for (int i = 0; i < first.length; i++) {
if (first[i] != second[i]) return false;
}
@@ -201,20 +236,19 @@
}
}
-/// Call structure with named arguments.
-class NamedCallStructure extends CallStructure {
+/// Call structure with named arguments. This is an implementation detail of the
+/// CallStructure interface.
+class _NamedCallStructure extends CallStructure {
@override
final List<String> namedArguments;
- final List<String> _orderedNamedArguments;
- NamedCallStructure(
- int argumentCount, List<String> namedArguments, int typeArgumentCount)
- : this._(argumentCount, namedArguments, typeArgumentCount, []);
+ /// The list of ordered named arguments is computed lazily. Initially `null`.
+ List<String> /*?*/ _orderedNamedArguments;
- NamedCallStructure._(int argumentCount, this.namedArguments,
+ _NamedCallStructure(int argumentCount, this.namedArguments,
int typeArgumentCount, this._orderedNamedArguments)
: assert(namedArguments.isNotEmpty),
- super.unnamed(argumentCount, typeArgumentCount);
+ super._(argumentCount, typeArgumentCount);
@override
bool get isNamed => true;
@@ -229,24 +263,29 @@
int get positionalArgumentCount => argumentCount - namedArgumentCount;
@override
- bool get isNormalized => namedArguments == _orderedNamedArguments;
+ bool get isNormalized =>
+ identical(namedArguments, getOrderedNamedArguments());
@override
- CallStructure toNormalized() => NamedCallStructure._(
- argumentCount,
- getOrderedNamedArguments(),
- typeArgumentCount,
- getOrderedNamedArguments());
+ CallStructure toNormalized() => isNormalized
+ ? this
+ : _NamedCallStructure(argumentCount, getOrderedNamedArguments(),
+ typeArgumentCount, getOrderedNamedArguments());
@override
List<String> getOrderedNamedArguments() {
- if (!_orderedNamedArguments.isEmpty) return _orderedNamedArguments;
+ return _orderedNamedArguments ??= _getOrderedNamedArguments();
+ }
- _orderedNamedArguments.addAll(namedArguments);
- _orderedNamedArguments.sort((String first, String second) {
- return first.compareTo(second);
- });
- return _orderedNamedArguments;
+ List<String> _getOrderedNamedArguments() {
+ List<String> ordered = List.of(namedArguments, growable: false);
+ ordered.sort((String first, String second) => first.compareTo(second));
+ // Use the same List if [namedArguments] is already ordered to indicate this
+ // _NamedCallStructure is normalized.
+ if (CallStructure._sameNames(ordered, namedArguments)) {
+ return namedArguments;
+ }
+ return ordered;
}
@override
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index 5235fe1..dddc39b 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -148,7 +148,7 @@
} else if (element.isConstructor) {
return Selector.callConstructor(name);
} else {
- throw failedAt(element, "Can't get selector from $element");
+ throw failedAt(element, "Cannot get selector from $element");
}
}
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
index e8ae525..af19b56 100644
--- a/pkg/dartdev/lib/src/analysis_server.dart
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -97,15 +97,16 @@
];
_process = await startDartProcess(sdk, command);
+ final proc = _process!;
// This callback hookup can't throw.
- _process!.exitCode.whenComplete(() => _process = null);
+ proc.exitCode.whenComplete(() => _process = null);
- final Stream<String> errorStream = _process!.stderr
+ final Stream<String> errorStream = proc.stderr
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter());
errorStream.listen(log.stderr);
- final Stream<String> inStream = _process!.stdout
+ final Stream<String> inStream = proc.stdout
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter());
inStream.listen(_handleServerResponse);
diff --git a/pkg/dartdev/test/utils.dart b/pkg/dartdev/test/utils.dart
index 316c8bc..145d519 100644
--- a/pkg/dartdev/test/utils.dart
+++ b/pkg/dartdev/test/utils.dart
@@ -130,11 +130,12 @@
],
workingDirectory: workingDir ?? dir.path,
environment: {if (logAnalytics) '_DARTDEV_LOG_ANALYTICS': 'true'});
- final stdoutContents = _process!.stdout.transform(utf8.decoder).join();
- final stderrContents = _process!.stderr.transform(utf8.decoder).join();
- final code = await _process!.exitCode;
+ final proc = _process!;
+ final stdoutContents = proc.stdout.transform(utf8.decoder).join();
+ final stderrContents = proc.stderr.transform(utf8.decoder).join();
+ final code = await proc.exitCode;
return ProcessResult(
- _process!.pid,
+ proc.pid,
code,
await stdoutContents,
await stderrContents,
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index ae632ec..880d764 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -25,13 +25,14 @@
export '../fasta/incremental_serializer.dart' show IncrementalSerializer;
abstract class IncrementalKernelGenerator {
- factory IncrementalKernelGenerator(CompilerOptions options, Uri entryPoint,
+ factory IncrementalKernelGenerator(
+ CompilerOptions options, List<Uri> entryPoints,
[Uri? initializeFromDillUri,
bool? outlineOnly,
IncrementalSerializer? incrementalSerializer]) {
return new IncrementalCompiler(
new CompilerContext(
- new ProcessedOptions(options: options, inputs: [entryPoint])),
+ new ProcessedOptions(options: options, inputs: entryPoints)),
initializeFromDillUri,
outlineOnly,
incrementalSerializer);
@@ -42,11 +43,11 @@
/// Notice that the component has to include the platform, and that no other
/// platform will be loaded.
factory IncrementalKernelGenerator.fromComponent(
- CompilerOptions options, Uri entryPoint, Component? component,
+ CompilerOptions options, List<Uri> entryPoints, Component? component,
[bool? outlineOnly, IncrementalSerializer? incrementalSerializer]) {
return new IncrementalCompiler.fromComponent(
new CompilerContext(
- new ProcessedOptions(options: options, inputs: [entryPoint])),
+ new ProcessedOptions(options: options, inputs: entryPoints)),
component,
outlineOnly,
incrementalSerializer);
@@ -63,10 +64,10 @@
/// Notice that the component has to include the platform, and that no other
/// platform will be loaded.
factory IncrementalKernelGenerator.forExpressionCompilationOnly(
- CompilerOptions options, Uri entryPoint, Component component) {
+ CompilerOptions options, List<Uri> entryPoints, Component component) {
return new IncrementalCompiler.forExpressionCompilationOnly(
new CompilerContext(
- new ProcessedOptions(options: options, inputs: [entryPoint])),
+ new ProcessedOptions(options: options, inputs: entryPoints)),
component);
}
diff --git a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
index ca6286c..39c7f32 100644
--- a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
@@ -45,16 +45,19 @@
/// The input [source] is expected to be a script with a main method, otherwise
/// an error is reported.
// TODO(sigmund): rename to kernelForScript?
-Future<CompilerResult?> kernelForProgram(
- Uri source, CompilerOptions options) async {
- return (await kernelForProgramInternal(source, options));
+Future<CompilerResult?> kernelForProgram(Uri source, CompilerOptions options,
+ {List<Uri> additionalSources: const <Uri>[]}) async {
+ return (await kernelForProgramInternal(source, options,
+ additionalSources: additionalSources));
}
Future<CompilerResult?> kernelForProgramInternal(
Uri source, CompilerOptions options,
- {bool retainDataForTesting: false, bool requireMain: true}) async {
- ProcessedOptions pOptions =
- new ProcessedOptions(options: options, inputs: [source]);
+ {List<Uri> additionalSources: const <Uri>[],
+ bool retainDataForTesting: false,
+ bool requireMain: true}) async {
+ ProcessedOptions pOptions = new ProcessedOptions(
+ options: options, inputs: [source, ...additionalSources]);
return await CompilerContext.runWithOptions(pOptions, (context) async {
CompilerResult result = await generateKernelInternal(
includeHierarchyAndCoreTypes: true,
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_target.dart b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
index b5b737e..1a0b447 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_target.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
@@ -12,6 +12,8 @@
import '../compiler_context.dart' show CompilerContext;
+import '../kernel/benchmarker.dart' show BenchmarkPhases, Benchmarker;
+
import '../messages.dart' show FormattedMessage, LocatedMessage, Message;
import '../ticker.dart' show Ticker;
@@ -40,7 +42,10 @@
/// Shared with [CompilerContext].
final Map<Uri, Source> uriToSource = CompilerContext.current.uriToSource;
- DillTarget(this.ticker, this.uriTranslator, this.backendTarget)
+ final Benchmarker? benchmarker;
+
+ DillTarget(this.ticker, this.uriTranslator, this.backendTarget,
+ {this.benchmarker})
// ignore: unnecessary_null_comparison
: assert(ticker != null),
// ignore: unnecessary_null_comparison
@@ -81,9 +86,12 @@
void buildOutlines({bool suppressFinalizationErrors: false}) {
if (loader.libraries.isNotEmpty) {
+ benchmarker?.enterPhase(BenchmarkPhases.dill_buildOutlines);
loader.buildOutlines();
+ benchmarker?.enterPhase(BenchmarkPhases.dill_finalizeExports);
loader.finalizeExports(
suppressFinalizationErrors: suppressFinalizationErrors);
+ benchmarker?.enterPhase(BenchmarkPhases.unknown);
}
isLoaded = true;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart b/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart
new file mode 100644
index 0000000..79df036
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Benchmarker {
+ final Stopwatch _totalStopwatch = new Stopwatch()..start();
+ final Stopwatch _phaseStopwatch = new Stopwatch()..start();
+ BenchmarkPhases _currentPhase = BenchmarkPhases.implicitInitialization;
+ List<PhaseTiming> _phaseTimings = [];
+
+ void enterPhase(BenchmarkPhases phase) {
+ if (_currentPhase == phase) return;
+ _phaseTimings.add(
+ new PhaseTiming(_currentPhase, _phaseStopwatch.elapsedMicroseconds));
+ _phaseStopwatch.reset();
+ _currentPhase = phase;
+ }
+
+ void stop() {
+ enterPhase(BenchmarkPhases.end);
+ _totalStopwatch.stop();
+ }
+
+ Map<String, Object?> toJson() {
+ // TODO: Merge unknown?
+ return <String, Object?>{
+ "totalTime": _totalStopwatch.elapsedMicroseconds,
+ "phases": _phaseTimings,
+ };
+ }
+}
+
+class PhaseTiming {
+ final BenchmarkPhases phase;
+ final int runtime;
+
+ PhaseTiming(this.phase, this.runtime);
+
+ Map<String, Object?> toJson() {
+ return <String, Object?>{
+ "phase": phase.name,
+ "runtime": runtime,
+ };
+ }
+}
+
+enum BenchmarkPhases {
+ implicitInitialization,
+ loadSDK,
+ loadAdditionalDills,
+
+ dill_buildOutlines,
+ dill_finalizeExports,
+
+ outline_kernelBuildOutlines,
+ outline_becomeCoreLibrary,
+ outline_resolveParts,
+ outline_computeMacroDeclarations,
+ outline_computeLibraryScopes,
+ outline_computeMacroApplications,
+ outline_setupTopAndBottomTypes,
+ outline_resolveTypes,
+ outline_computeVariances,
+ outline_computeDefaultTypes,
+ outline_applyTypeMacros,
+ outline_checkSemantics,
+ outline_finishTypeVariables,
+ outline_createTypeInferenceEngine,
+ outline_buildComponent,
+ outline_installDefaultSupertypes,
+ outline_installSyntheticConstructors,
+ outline_resolveConstructors,
+ outline_link,
+ outline_computeCoreTypes,
+ outline_buildClassHierarchy,
+ outline_checkSupertypes,
+ outline_applyDeclarationMacros,
+ outline_buildClassHierarchyMembers,
+ outline_computeHierarchy,
+ outline_computeShowHideElements,
+ outline_installTypedefTearOffs,
+ outline_performTopLevelInference,
+ outline_checkOverrides,
+ outline_checkAbstractMembers,
+ outline_addNoSuchMethodForwarders,
+ outline_checkMixins,
+ outline_buildOutlineExpressions,
+ outline_checkTypes,
+ outline_checkRedirectingFactories,
+ outline_finishSynthesizedParameters,
+ outline_checkMainMethods,
+ outline_installAllComponentProblems,
+
+ body_buildBodies,
+ body_finishSynthesizedParameters,
+
+ body_finishDeferredLoadTearoffs,
+ body_finishNoSuchMethodForwarders,
+ body_collectSourceClasses,
+ body_applyDefinitionMacros,
+ body_finishNativeMethods,
+ body_finishPatchMethods,
+ body_finishAllConstructors,
+ body_runBuildTransformations,
+ body_verify,
+ body_installAllComponentProblems,
+
+ printComponentText,
+ omitPlatform,
+ writeComponent,
+ // add more here
+ //
+ end,
+ unknown,
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index d01d2d8..6ac5ea0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -72,6 +72,7 @@
import '../ticker.dart' show Ticker;
import '../type_inference/type_schema.dart';
import '../uri_translator.dart' show UriTranslator;
+import 'benchmarker.dart' show BenchmarkPhases, Benchmarker;
import 'constant_evaluator.dart' as constants
show
EvaluationMode,
@@ -182,12 +183,15 @@
final ProcessedOptions _options;
+ final Benchmarker? benchmarker;
+
KernelTarget(this.fileSystem, this.includeComments, DillTarget dillTarget,
this.uriTranslator)
: dillTarget = dillTarget,
backendTarget = dillTarget.backendTarget,
_options = CompilerContext.current.options,
- ticker = dillTarget.ticker {
+ ticker = dillTarget.ticker,
+ benchmarker = dillTarget.benchmarker {
loader = createLoader();
}
@@ -399,10 +403,20 @@
_hasComputedNeededPrecompilations = true;
if (loader.first == null) return null;
return withCrashReporting<NeededPrecompilations?>(() async {
+ benchmarker?.enterPhase(BenchmarkPhases.outline_kernelBuildOutlines);
await loader.buildOutlines();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_becomeCoreLibrary);
loader.coreLibrary.becomeCoreLibrary();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_resolveParts);
loader.resolveParts();
- return loader.computeMacroDeclarations();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_computeMacroDeclarations);
+ NeededPrecompilations? result = loader.computeMacroDeclarations();
+
+ benchmarker?.enterPhase(BenchmarkPhases.unknown);
+ return result;
}, () => loader.currentUriForCrashReporting);
}
@@ -423,56 +437,135 @@
throw new UnsupportedError('Macro precompilation is not supported.');
}
}
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_computeLibraryScopes);
loader.computeLibraryScopes();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_computeMacroApplications);
MacroApplications? macroApplications =
await loader.computeMacroApplications();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_setupTopAndBottomTypes);
setupTopAndBottomTypes();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_resolveTypes);
loader.resolveTypes();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_computeVariances);
loader.computeVariances();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_computeDefaultTypes);
loader.computeDefaultTypes(
dynamicType, nullType, bottomType, objectClassBuilder);
+
if (macroApplications != null) {
+ benchmarker?.enterPhase(BenchmarkPhases.outline_applyTypeMacros);
await macroApplications.applyTypeMacros();
}
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_checkSemantics);
List<SourceClassBuilder>? sourceClassBuilders =
loader.checkSemantics(objectClassBuilder);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_finishTypeVariables);
loader.finishTypeVariables(objectClassBuilder, dynamicType);
+
+ benchmarker
+ ?.enterPhase(BenchmarkPhases.outline_createTypeInferenceEngine);
loader.createTypeInferenceEngine();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_buildComponent);
loader.buildComponent();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_installDefaultSupertypes);
installDefaultSupertypes();
+
+ benchmarker
+ ?.enterPhase(BenchmarkPhases.outline_installSyntheticConstructors);
installSyntheticConstructors(sourceClassBuilders);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_resolveConstructors);
loader.resolveConstructors();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_link);
component =
link(new List<Library>.of(loader.libraries), nameRoot: nameRoot);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_computeCoreTypes);
computeCoreTypes();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_buildClassHierarchy);
loader.buildClassHierarchy(sourceClassBuilders, objectClassBuilder);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_checkSupertypes);
loader.checkSupertypes(sourceClassBuilders, enumClass);
+
if (macroApplications != null) {
+ benchmarker?.enterPhase(BenchmarkPhases.outline_applyDeclarationMacros);
await macroApplications
.applyDeclarationsMacros(loader.hierarchyBuilder);
}
+
+ benchmarker
+ ?.enterPhase(BenchmarkPhases.outline_buildClassHierarchyMembers);
loader.buildClassHierarchyMembers(sourceClassBuilders);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_computeHierarchy);
loader.computeHierarchy();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_computeShowHideElements);
loader.computeShowHideElements();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_installTypedefTearOffs);
loader.installTypedefTearOffs();
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_performTopLevelInference);
loader.performTopLevelInference(sourceClassBuilders);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_checkOverrides);
loader.checkOverrides(sourceClassBuilders);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_checkAbstractMembers);
loader.checkAbstractMembers(sourceClassBuilders);
+
+ benchmarker
+ ?.enterPhase(BenchmarkPhases.outline_addNoSuchMethodForwarders);
loader.addNoSuchMethodForwarders(sourceClassBuilders);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_checkMixins);
loader.checkMixins(sourceClassBuilders);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_buildOutlineExpressions);
loader.buildOutlineExpressions(
loader.hierarchy, synthesizedFunctionNodes);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_checkTypes);
loader.checkTypes();
+
+ benchmarker
+ ?.enterPhase(BenchmarkPhases.outline_checkRedirectingFactories);
loader.checkRedirectingFactories(sourceClassBuilders);
+
+ benchmarker
+ ?.enterPhase(BenchmarkPhases.outline_finishSynthesizedParameters);
finishSynthesizedParameters(forOutline: true);
+
+ benchmarker?.enterPhase(BenchmarkPhases.outline_checkMainMethods);
loader.checkMainMethods();
+
+ benchmarker
+ ?.enterPhase(BenchmarkPhases.outline_installAllComponentProblems);
installAllComponentProblems(loader.allComponentProblems);
loader.allComponentProblems.clear();
+
+ benchmarker?.enterPhase(BenchmarkPhases.unknown);
+
// For whatever reason sourceClassBuilders is kept alive for some amount
// of time, meaning that all source library builders will be kept alive
// (for whatever amount of time) even though we convert them to dill
// library builders. To avoid it we null it out here.
sourceClassBuilders = null;
+
return new BuildResult(
component: component, macroApplications: macroApplications);
}, () => loader.currentUriForCrashReporting);
@@ -494,22 +587,50 @@
}
return withCrashReporting<BuildResult>(() async {
ticker.logMs("Building component");
+
+ benchmarker?.enterPhase(BenchmarkPhases.body_buildBodies);
await loader.buildBodies();
+
+ benchmarker?.enterPhase(BenchmarkPhases.body_finishSynthesizedParameters);
finishSynthesizedParameters();
+
+ benchmarker?.enterPhase(BenchmarkPhases.body_finishDeferredLoadTearoffs);
loader.finishDeferredLoadTearoffs();
+
+ benchmarker
+ ?.enterPhase(BenchmarkPhases.body_finishNoSuchMethodForwarders);
loader.finishNoSuchMethodForwarders();
+
+ benchmarker?.enterPhase(BenchmarkPhases.body_collectSourceClasses);
List<SourceClassBuilder>? sourceClasses = loader.collectSourceClasses();
+
if (macroApplications != null) {
+ benchmarker?.enterPhase(BenchmarkPhases.body_applyDefinitionMacros);
await macroApplications.applyDefinitionMacros();
}
+
+ benchmarker?.enterPhase(BenchmarkPhases.body_finishNativeMethods);
loader.finishNativeMethods();
+
+ benchmarker?.enterPhase(BenchmarkPhases.body_finishPatchMethods);
loader.finishPatchMethods();
+
+ benchmarker?.enterPhase(BenchmarkPhases.body_finishAllConstructors);
finishAllConstructors(sourceClasses);
+
+ benchmarker?.enterPhase(BenchmarkPhases.body_runBuildTransformations);
runBuildTransformations();
- if (verify) this.verify();
+ if (verify) {
+ benchmarker?.enterPhase(BenchmarkPhases.body_verify);
+ this.verify();
+ }
+
+ benchmarker?.enterPhase(BenchmarkPhases.body_installAllComponentProblems);
installAllComponentProblems(loader.allComponentProblems);
+ benchmarker?.enterPhase(BenchmarkPhases.unknown);
+
// For whatever reason sourceClasses is kept alive for some amount
// of time, meaning that all source library builders will be kept alive
// (for whatever amount of time) even though we convert them to dill
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index 995a036..bec7d02 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -9,7 +9,7 @@
import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart'
as macro;
import 'package:front_end/src/base/common.dart';
-import 'package:kernel/ast.dart' show DartType, DynamicType;
+import 'package:kernel/ast.dart' show DartType;
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/src/types.dart';
import 'package:kernel/type_environment.dart' show SubtypeCheckMode;
@@ -20,6 +20,7 @@
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
import '../builder/named_type_builder.dart';
+import '../builder/nullability_builder.dart';
import '../builder/type_builder.dart';
import '../identifiers.dart';
import '../source/source_class_builder.dart';
@@ -166,7 +167,8 @@
return new MacroApplications(macroExecutor, libraryData, dataForTesting);
}
- Map<SourceClassBuilder, macro.ClassDeclaration?> _classDeclarations = {};
+ Map<SourceClassBuilder, macro.ClassDeclaration> _classDeclarations = {};
+ Map<macro.ClassDeclaration, SourceClassBuilder> _classBuilders = {};
Map<MemberBuilder, macro.Declaration?> _memberDeclarations = {};
// TODO(johnniwinther): Support all members.
@@ -179,6 +181,10 @@
return _classDeclarations[builder] ??= _createClassDeclaration(builder);
}
+ SourceClassBuilder _getClassBuilder(macro.ClassDeclaration declaration) {
+ return _classBuilders[declaration]!;
+ }
+
macro.Declaration _createMemberDeclaration(MemberBuilder memberBuilder) {
if (memberBuilder is SourceProcedureBuilder) {
return _createFunctionDeclaration(memberBuilder);
@@ -297,7 +303,7 @@
ClassHierarchyBase classHierarchy) async {
types = new Types(classHierarchy);
typeResolver = new _TypeResolver(this);
- classIntrospector = new _ClassIntrospector();
+ classIntrospector = new _ClassIntrospector(this);
await _applyMacros(_applyDeclarationsMacros);
}
@@ -344,7 +350,7 @@
}
macro.ClassDeclaration _createClassDeclaration(SourceClassBuilder builder) {
- return new macro.ClassDeclarationImpl(
+ macro.ClassDeclaration declaration = new macro.ClassDeclarationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: new macro.IdentifierImpl(
id: macro.RemoteInstance.uniqueId, name: builder.name),
@@ -358,6 +364,8 @@
mixins: [],
// TODO(johnniwinther): Support superclass
superclass: null);
+ _classBuilders[declaration] = builder;
+ return declaration;
}
List<List<macro.ParameterDeclarationImpl>> _createParameters(
@@ -372,25 +380,24 @@
for (FormalParameterBuilder formal in formals) {
macro.TypeAnnotationImpl type =
computeTypeAnnotation(builder.library, formal.type);
- // TODO(johnniwinther): Support default values.
if (formal.isNamed) {
namedParameters.add(new macro.ParameterDeclarationImpl(
- id: macro.RemoteInstance.uniqueId,
- identifier: new macro.IdentifierImpl(
- id: macro.RemoteInstance.uniqueId, name: formal.name),
- isRequired: formal.isNamedRequired,
- isNamed: true,
- type: type,
- defaultValue: null));
+ id: macro.RemoteInstance.uniqueId,
+ identifier: new macro.IdentifierImpl(
+ id: macro.RemoteInstance.uniqueId, name: formal.name),
+ isRequired: formal.isNamedRequired,
+ isNamed: true,
+ type: type,
+ ));
} else {
positionalParameters.add(new macro.ParameterDeclarationImpl(
- id: macro.RemoteInstance.uniqueId,
- identifier: new macro.IdentifierImpl(
- id: macro.RemoteInstance.uniqueId, name: formal.name),
- isRequired: formal.isRequired,
- isNamed: false,
- type: type,
- defaultValue: null));
+ id: macro.RemoteInstance.uniqueId,
+ identifier: new macro.IdentifierImpl(
+ id: macro.RemoteInstance.uniqueId, name: formal.name),
+ isRequired: formal.isRequired,
+ isNamed: false,
+ type: type,
+ ));
}
}
}
@@ -518,8 +525,6 @@
identifier: new macro.IdentifierImpl(
id: macro.RemoteInstance.uniqueId, name: builder.name),
definingClass: definingClass.identifier as macro.IdentifierImpl,
- // TODO(johnniwinther): Support initializer.
- initializer: null,
isExternal: builder.isExternal,
isFinal: builder.isFinal,
isLate: builder.isLate,
@@ -529,8 +534,6 @@
id: macro.RemoteInstance.uniqueId,
identifier: new macro.IdentifierImpl(
id: macro.RemoteInstance.uniqueId, name: builder.name),
- // TODO(johnniwinther): Support initializer.
- initializer: null,
isExternal: builder.isExternal,
isFinal: builder.isFinal,
isLate: builder.isLate,
@@ -538,7 +541,7 @@
}
}
- Map<TypeBuilder?, _NamedTypeAnnotationImpl> _typeAnnotationCache = {};
+ Map<TypeBuilder?, macro.TypeAnnotationImpl> _typeAnnotationCache = {};
List<macro.TypeAnnotationImpl> computeTypeAnnotations(
LibraryBuilder library, List<TypeBuilder>? typeBuilders) {
@@ -547,7 +550,7 @@
(int index) => computeTypeAnnotation(library, typeBuilders[index]));
}
- _NamedTypeAnnotationImpl _computeTypeAnnotation(
+ macro.TypeAnnotationImpl _computeTypeAnnotation(
LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
if (typeBuilder != null) {
if (typeBuilder is NamedTypeBuilder) {
@@ -556,21 +559,22 @@
computeTypeAnnotations(libraryBuilder, typeBuilder.arguments);
bool isNullable = typeBuilder.nullabilityBuilder.isNullable;
if (name is String) {
- return new _NamedTypeAnnotationImpl(
- typeBuilder: typeBuilder,
- libraryBuilder: libraryBuilder,
+ return new macro.NamedTypeAnnotationImpl(
id: macro.RemoteInstance.uniqueId,
- identifier: new macro.IdentifierImpl(
- id: macro.RemoteInstance.uniqueId, name: name),
+ identifier: new _IdentifierImpl(
+ typeBuilder: typeBuilder,
+ libraryBuilder: libraryBuilder,
+ id: macro.RemoteInstance.uniqueId,
+ name: name),
typeArguments: typeArguments,
isNullable: isNullable);
} else if (name is QualifiedName) {
assert(name.qualifier is String);
- return new _NamedTypeAnnotationImpl(
- typeBuilder: typeBuilder,
- libraryBuilder: libraryBuilder,
+ return new macro.NamedTypeAnnotationImpl(
id: macro.RemoteInstance.uniqueId,
- identifier: new macro.IdentifierImpl(
+ identifier: new _IdentifierImpl(
+ typeBuilder: typeBuilder,
+ libraryBuilder: libraryBuilder,
id: macro.RemoteInstance.uniqueId,
// TODO: We probably shouldn't be including the qualifier
// here. Kernel should probably have its own implementation
@@ -582,9 +586,7 @@
}
}
}
- return new _NamedTypeAnnotationImpl(
- typeBuilder: typeBuilder,
- libraryBuilder: libraryBuilder,
+ return new macro.NamedTypeAnnotationImpl(
id: macro.RemoteInstance.uniqueId,
identifier: dynamicIdentifier,
isNullable: false,
@@ -597,17 +599,51 @@
_computeTypeAnnotation(libraryBuilder, typeBuilder);
}
- macro.StaticType resolveTypeAnnotation(
- _NamedTypeAnnotationImpl typeAnnotation) {
- TypeBuilder? typeBuilder = typeAnnotation.typeBuilder;
- LibraryBuilder libraryBuilder = typeAnnotation.libraryBuilder;
- DartType dartType;
- if (typeBuilder != null) {
- dartType = typeBuilder.build(libraryBuilder);
+ TypeBuilder _typeBuilderForAnnotation(
+ macro.TypeAnnotationCode typeAnnotation) {
+ NullabilityBuilder nullabilityBuilder;
+ if (typeAnnotation is macro.NullableTypeAnnotationCode) {
+ nullabilityBuilder = const NullabilityBuilder.nullable();
+ typeAnnotation = typeAnnotation.underlyingType;
} else {
- dartType = const DynamicType();
+ nullabilityBuilder = const NullabilityBuilder.omitted();
}
- return createStaticType(dartType);
+
+ if (typeAnnotation is macro.NamedTypeAnnotationCode) {
+ _IdentifierImpl typeIdentifier = typeAnnotation.name as _IdentifierImpl;
+ TypeBuilder? originalTypeBuilder = typeIdentifier.typeBuilder;
+ if (originalTypeBuilder == null) {
+ throw new StateError('No type builder for $typeIdentifier');
+ }
+ if (originalTypeBuilder is! NamedTypeBuilder) {
+ throw new StateError(
+ 'Type $typeIdentifier was not a named type as expected!');
+ }
+ List<TypeBuilder> arguments = [
+ for (macro.TypeAnnotationCode argumentCode
+ in typeAnnotation.typeArguments)
+ _typeBuilderForAnnotation(argumentCode),
+ ];
+
+ return new NamedTypeBuilder.fromTypeDeclarationBuilder(
+ originalTypeBuilder.declaration!, nullabilityBuilder,
+ instanceTypeVariableAccess:
+ originalTypeBuilder.instanceTypeVariableAccess,
+ arguments: arguments);
+ }
+ // TODO: Implement support for function types.
+ throw new UnimplementedError(
+ 'Unimplemented type annotation kind ${typeAnnotation.kind}');
+ }
+
+ macro.StaticType resolveTypeAnnotation(
+ macro.TypeAnnotationCode typeAnnotation) {
+ TypeBuilder typeBuilder = _typeBuilderForAnnotation(typeAnnotation);
+ // TODO: This should probably be passed in instead, possibly attached to the
+ // TypeResolver class?
+ LibraryBuilder libraryBuilder =
+ typeAnnotation.parts.whereType<_IdentifierImpl>().first.libraryBuilder;
+ return createStaticType(typeBuilder.build(libraryBuilder));
}
Map<DartType, _StaticTypeImpl> _staticTypeCache = {};
@@ -617,22 +653,16 @@
}
}
-class _NamedTypeAnnotationImpl extends macro.NamedTypeAnnotationImpl {
+class _IdentifierImpl extends macro.IdentifierImpl {
final TypeBuilder? typeBuilder;
final LibraryBuilder libraryBuilder;
- _NamedTypeAnnotationImpl({
+ _IdentifierImpl({
required this.typeBuilder,
required this.libraryBuilder,
required int id,
- required bool isNullable,
- required macro.IdentifierImpl identifier,
- required List<macro.TypeAnnotationImpl> typeArguments,
- }) : super(
- id: id,
- isNullable: isNullable,
- identifier: identifier,
- typeArguments: typeArguments);
+ required String name,
+ }) : super(id: id, name: name);
}
class _StaticTypeImpl extends macro.StaticType {
@@ -659,31 +689,49 @@
_TypeResolver(this.macroApplications);
@override
- Future<macro.StaticType> instantiateCode(macro.ExpressionCode code) {
- // TODO: implement instantiateCode
- throw new UnimplementedError();
- }
-
- @override
- Future<macro.StaticType> instantiateType(
- covariant _NamedTypeAnnotationImpl typeAnnotation) {
+ Future<macro.StaticType> resolve(macro.TypeAnnotationCode typeAnnotation) {
return new Future.value(
macroApplications.resolveTypeAnnotation(typeAnnotation));
}
}
class _ClassIntrospector implements macro.ClassIntrospector {
+ final MacroApplications macroApplications;
+
+ _ClassIntrospector(this.macroApplications);
+
@override
Future<List<macro.ConstructorDeclaration>> constructorsOf(
macro.ClassDeclaration clazz) {
- // TODO: implement constructorsOf
- throw new UnimplementedError('_ClassIntrospector.constructorsOf');
+ ClassBuilder classBuilder = macroApplications._getClassBuilder(clazz);
+ List<macro.ConstructorDeclaration> result = [];
+ classBuilder.forEachConstructor((_, MemberBuilder memberBuilder) {
+ if (memberBuilder is DeclaredSourceConstructorBuilder) {
+ // TODO(johnniwinther): Should we support synthesized constructors?
+ result.add(macroApplications._getMemberDeclaration(memberBuilder)
+ as macro.ConstructorDeclaration);
+ }
+ });
+ classBuilder.forEach((_, Builder memberBuilder) {
+ if (memberBuilder is SourceFactoryBuilder) {
+ result.add(macroApplications._getMemberDeclaration(memberBuilder)
+ as macro.ConstructorDeclaration);
+ }
+ });
+ return new Future.value(result);
}
@override
Future<List<macro.FieldDeclaration>> fieldsOf(macro.ClassDeclaration clazz) {
- // TODO: implement fieldsOf
- throw new UnimplementedError('_ClassIntrospector.fieldsOf');
+ ClassBuilder classBuilder = macroApplications._getClassBuilder(clazz);
+ List<macro.FieldDeclaration> result = [];
+ classBuilder.forEach((_, Builder memberBuilder) {
+ if (memberBuilder is SourceFieldBuilder) {
+ result.add(macroApplications._getMemberDeclaration(memberBuilder)
+ as macro.FieldDeclaration);
+ }
+ });
+ return new Future.value(result);
}
@override
@@ -696,8 +744,15 @@
@override
Future<List<macro.MethodDeclaration>> methodsOf(
macro.ClassDeclaration clazz) {
- // TODO: implement methodsOf
- throw new UnimplementedError('_ClassIntrospector.methodsOf');
+ ClassBuilder classBuilder = macroApplications._getClassBuilder(clazz);
+ List<macro.MethodDeclaration> result = [];
+ classBuilder.forEach((_, Builder memberBuilder) {
+ if (memberBuilder is SourceProcedureBuilder) {
+ result.add(macroApplications._getMemberDeclaration(memberBuilder)
+ as macro.MethodDeclaration);
+ }
+ });
+ return new Future.value(result);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index e90cf3d..90ad778 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -2570,6 +2570,8 @@
_completeOnAsyncReturn(_future, value, async_jump_var) {}
+_completeWithNoFutureOnAsyncReturn(_future, value, async_jump_var) {}
+
_completeOnAsyncError(_future, e, st, async_jump_var) {}
class _AsyncStarStreamController {
diff --git a/pkg/front_end/test/hot_reload_e2e_test.dart b/pkg/front_end/test/hot_reload_e2e_test.dart
index 69069c9..86ddcb0 100644
--- a/pkg/front_end/test/hot_reload_e2e_test.dart
+++ b/pkg/front_end/test/hot_reload_e2e_test.dart
@@ -309,7 +309,7 @@
..fileSystem = fs
..target = new VmTarget(new TargetFlags())
..environmentDefines = {};
- return new IncrementalKernelGenerator(options, entryUri);
+ return new IncrementalKernelGenerator(options, [entryUri]);
}
Future<bool> rebuild(IncrementalKernelGenerator compiler, Uri outputUri) async {
diff --git a/pkg/front_end/test/incremental_bulk_compiler_full.dart b/pkg/front_end/test/incremental_bulk_compiler_full.dart
index 9edfd97..0856796 100644
--- a/pkg/front_end/test/incremental_bulk_compiler_full.dart
+++ b/pkg/front_end/test/incremental_bulk_compiler_full.dart
@@ -76,7 +76,7 @@
late List<int> oneShotSerialized;
try {
IncrementalKernelGenerator compiler =
- new IncrementalKernelGenerator(getOptions(), uri);
+ new IncrementalKernelGenerator(getOptions(), [uri]);
oneShotSerialized =
util.postProcess((await compiler.computeDelta()).component);
} catch (e) {
@@ -89,7 +89,7 @@
try {
globalDebuggingNames = new NameSystem();
if (context.compiler == null) {
- context.compiler = new IncrementalKernelGenerator(getOptions(), uri);
+ context.compiler = new IncrementalKernelGenerator(getOptions(), [uri]);
}
IncrementalCompilerResult compilerResult = await context.compiler!
.computeDelta(entryPoints: [uri], fullComponent: true);
@@ -106,7 +106,7 @@
try {
globalDebuggingNames = new NameSystem();
if (context.compiler == null) {
- context.compiler = new IncrementalKernelGenerator(getOptions(), uri);
+ context.compiler = new IncrementalKernelGenerator(getOptions(), [uri]);
}
IncrementalCompilerResult compilerResult = await context.compiler!
.computeDelta(entryPoints: [uri], fullComponent: true);
diff --git a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
index 23e4ee1..a6dbe4e 100644
--- a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
+++ b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
@@ -28,9 +28,9 @@
if (function.positionalParameters.isEmpty) {
return;
}
- StaticType returnType = await builder.instantiateType(function.returnType);
+ StaticType returnType = await builder.resolve(function.returnType.code);
StaticType parameterType =
- await builder.instantiateType(function.positionalParameters.first.type);
+ await builder.resolve(function.positionalParameters.first.type.code);
builder.augment(new FunctionBodyCode.fromString('''{
print('isExactly=${await returnType.isExactly(parameterType)}');
print('isSubtype=${await returnType.isSubtypeOf(parameterType)}');
@@ -90,9 +90,9 @@
if (function.positionalParameters.isEmpty) {
return;
}
- StaticType returnType = await builder.instantiateType(function.returnType);
+ StaticType returnType = await builder.resolve(function.returnType.code);
StaticType parameterType =
- await builder.instantiateType(function.positionalParameters.first.type);
+ await builder.resolve(function.positionalParameters.first.type.code);
bool isExactly = await returnType.isExactly(parameterType);
bool isSubtype = await returnType.isSubtypeOf(parameterType);
String tag = '${isExactly ? 'e' : ''}${isSubtype ? 's' : ''}';
@@ -199,6 +199,59 @@
macro
+class ClassDeclarationsMacro2 implements ClassDeclarationsMacro {
+ const ClassDeclarationsMacro2();
+
+ FutureOr<void> buildDeclarationsForClass(ClassDeclaration clazz,
+ ClassMemberDeclarationBuilder builder) async {
+ List<ConstructorDeclaration> constructors = await builder.constructorsOf(
+ clazz);
+ StringBuffer constructorsText = new StringBuffer();
+ String comma = '';
+ constructorsText.write('constructors=');
+ for (ConstructorDeclaration constructor in constructors) {
+ constructorsText.write(comma);
+ String name = constructor.identifier.name;
+ constructorsText.write("'$name'");
+ comma = ',';
+ }
+
+ List<FieldDeclaration> fields = await builder.fieldsOf(
+ clazz);
+ StringBuffer fieldsText = new StringBuffer();
+ comma = '';
+ fieldsText.write('fields=');
+ for (FieldDeclaration field in fields) {
+ fieldsText.write(comma);
+ String name = field.identifier.name;
+ fieldsText.write("'$name'");
+ comma = ',';
+ }
+
+ List<MethodDeclaration> methods = await builder.methodsOf(
+ clazz);
+ StringBuffer methodsText = new StringBuffer();
+ comma = '';
+ methodsText.write('methods=');
+ for (MethodDeclaration method in methods) {
+ methodsText.write(comma);
+ String name = method.identifier.name;
+ methodsText.write("'$name'");
+ comma = ',';
+ }
+
+ builder.declareInLibrary(new DeclarationCode.fromString('''
+void ${clazz.identifier.name}Introspection() {
+ print("$constructorsText");
+ print("$fieldsText");
+ print("$methodsText");
+}
+'''));
+ }
+}
+
+macro
+
class ConstructorDeclarationsMacro1
implements ConstructorDeclarationsMacro {
const ConstructorDeclarationsMacro1();
diff --git a/pkg/front_end/test/macro_application/data/tests/declarations.dart b/pkg/front_end/test/macro_application/data/tests/declarations.dart
index cf13538..c4584d6 100644
--- a/pkg/front_end/test/macro_application/data/tests/declarations.dart
+++ b/pkg/front_end/test/macro_application/data/tests/declarations.dart
@@ -54,8 +54,15 @@
/*class: Class1:
void Class1GeneratedMethod_() {}
+
+void Class1Introspection() {
+ print("constructors=''");
+ print("fields='instanceField1','instanceField2','instanceField3'");
+ print("methods='instanceMethod1','instanceGetter1','[]','instanceSetter1'");
+}
*/
@ClassDeclarationsMacro1()
+@ClassDeclarationsMacro2()
class Class1 {
/*member: Class1.:
augment class Class1 {
@@ -126,8 +133,15 @@
/*class: Class2:
void Class2GeneratedMethod_a() {}
+
+void Class2Introspection() {
+ print("constructors=");
+ print("fields='instanceField1'");
+ print("methods='instanceMethod1'");
+}
*/
@ClassDeclarationsMacro1()
+@ClassDeclarationsMacro2()
abstract class Class2 {
/*member: Class2.instanceMethod1:
void Class2_instanceMethod1GeneratedMethod_a() {}
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 7ddc634..3423497 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -107,6 +107,7 @@
belonging
beloning
benchmark
+benchmarker
benchmarks
bf
bi
@@ -1286,6 +1287,7 @@
tiki
tilde
till
+timings
tiny
tj
tm
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index b71a7ff..1714002 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -64,6 +64,8 @@
bbb
bc
bench
+benchmarker
+benchmarkers
besides
beta
bigger
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect
index adcb97b..aaa0017 100644
--- a/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect
@@ -28,7 +28,7 @@
static method Extension|asyncMethod(lowered final core::int* #this) → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -37,7 +37,7 @@
try {
#L1:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect
index 4e5d4b5..cda03dd 100644
--- a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect
@@ -17,7 +17,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -38,7 +38,7 @@
self::expect(87, let final core::Object* #t11 = CheckLibraryIsLoaded(prefix) in def::Extension|staticProperty = 87);
self::expect(87, let final core::Object* #t12 = CheckLibraryIsLoaded(prefix) in def::Extension|staticMethod());
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect
index 299f5f6..52535cd 100644
--- a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -29,7 +29,7 @@
self::expect(87, let final core::Object* #t7 = CheckLibraryIsLoaded(prefix) in def::topLevelProperty);
self::expect(87, let final core::Object* #t8 = CheckLibraryIsLoaded(prefix) in def::topLevelMethod());
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
index 295921a..4b96489 100644
--- a/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
static method asyncString() → asy::Future<core::String*>* /* originally async */ {
final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
core::bool* :is_sync = false;
- FutureOr<core::String*>* :return_value;
+ core::String? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -22,7 +22,7 @@
:return_value = "foo";
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -181,7 +181,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -194,7 +194,7 @@
[yield] let dynamic #t2 = asy::_awaitHelper(self::asyncString(), :async_op_then, :async_op_error, :async_op) in null;
core::String* str = _in::unsafeCast<core::String*>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart b/pkg/front_end/testcases/general/async_function_returns_future_or.dart
new file mode 100644
index 0000000..8a4d911
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+main() async {
+ await returnsString();
+ await returnsFutureOrString();
+ await returnsAwaitFutureOrString();
+ await returnsFutureString();
+ await returnsAwaitFutureString();
+ await returnsObject();
+ await returnsFutureOrObject();
+ await returnsAwaitFutureOrObject();
+ await returnsFutureObject();
+ await returnsAwaitFutureObject();
+}
+
+Future<String> returnsString() async => 'a';
+Future<String> returnsFutureOrString() async => getFutureOr<String>('a');
+Future<String> returnsAwaitFutureOrString() async =>
+ await getFutureOr<String>('a');
+Future<String> returnsFutureString() async => getFuture<String>('a');
+FutureOr<String> returnsAwaitFutureString() async =>
+ await getFuture<String>('a');
+
+Future<Object> returnsObject() async => Object();
+Future<Object> returnsFutureOrObject() async => getFutureOr<Object>(Object());
+Future<Object> returnsAwaitFutureOrObject() async =>
+ await getFutureOr<Object>(Object());
+Future<Object> returnsFutureObject() async => getFuture<Object>(Object());
+FutureOr<Object> returnsAwaitFutureObject() async =>
+ await getFuture<Object>(Object());
+
+FutureOr<T> getFutureOr<T>(T v) async => v;
+Future<T> getFuture<T>(T v) async => v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline.expect
new file mode 100644
index 0000000..94a1eca
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+import 'dart:async';
+
+main() async {}
+Future<String> returnsString() async => 'a';
+Future<String> returnsFutureOrString() async => getFutureOr<String>('a');
+Future<String> returnsAwaitFutureOrString() async =>
+ await getFutureOr<String>('a');
+Future<String> returnsFutureString() async => getFuture<String>('a');
+FutureOr<String> returnsAwaitFutureString() async =>
+ await getFuture<String>('a');
+Future<Object> returnsObject() async => Object();
+Future<Object> returnsFutureOrObject() async => getFutureOr<Object>(Object());
+Future<Object> returnsAwaitFutureOrObject() async =>
+ await getFutureOr<Object>(Object());
+Future<Object> returnsFutureObject() async => getFuture<Object>(Object());
+FutureOr<Object> returnsAwaitFutureObject() async =>
+ await getFuture<Object>(Object());
+FutureOr<T> getFutureOr<T>(T v) async => v;
+Future<T> getFuture<T>(T v) async => v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..41cf593
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+import 'dart:async';
+
+Future<Object> returnsAwaitFutureOrObject() async =>
+ await getFutureOr<Object>(Object());
+Future<Object> returnsFutureObject() async => getFuture<Object>(Object());
+Future<Object> returnsFutureOrObject() async => getFutureOr<Object>(Object());
+Future<Object> returnsObject() async => Object();
+Future<String> returnsAwaitFutureOrString() async =>
+ await getFutureOr<String>('a');
+Future<String> returnsFutureOrString() async => getFutureOr<String>('a');
+Future<String> returnsFutureString() async => getFuture<String>('a');
+Future<String> returnsString() async => 'a';
+Future<T> getFuture<T>(T v) async => v;
+FutureOr<Object> returnsAwaitFutureObject() async =>
+ await getFuture<Object>(Object());
+FutureOr<String> returnsAwaitFutureString() async =>
+ await getFuture<String>('a');
+FutureOr<T> getFutureOr<T>(T v) async => v;
+main() async {}
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.expect
new file mode 100644
index 0000000..6f8e4d4
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.expect
@@ -0,0 +1,43 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method main() → dynamic async {
+ await self::returnsString();
+ await self::returnsFutureOrString();
+ await self::returnsAwaitFutureOrString();
+ await self::returnsFutureString();
+ await self::returnsAwaitFutureString();
+ await self::returnsObject();
+ await self::returnsFutureOrObject();
+ await self::returnsAwaitFutureOrObject();
+ await self::returnsFutureObject();
+ await self::returnsAwaitFutureObject();
+}
+static method returnsString() → asy::Future<core::String> async
+ return "a";
+static method returnsFutureOrString() → asy::Future<core::String> async
+ return self::getFutureOr<core::String>("a");
+static method returnsAwaitFutureOrString() → asy::Future<core::String> async
+ return await self::getFutureOr<core::String>("a");
+static method returnsFutureString() → asy::Future<core::String> async
+ return self::getFuture<core::String>("a");
+static method returnsAwaitFutureString() → FutureOr<core::String> async
+ return await self::getFuture<core::String>("a");
+static method returnsObject() → asy::Future<core::Object> async
+ return new core::Object::•();
+static method returnsFutureOrObject() → asy::Future<core::Object> async
+ return self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> async
+ return await self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsFutureObject() → asy::Future<core::Object> async
+ return self::getFuture<core::Object>(new core::Object::•());
+static method returnsAwaitFutureObject() → FutureOr<core::Object> async
+ return await self::getFuture<core::Object>(new core::Object::•());
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> async
+ return v;
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> async
+ return v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.modular.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.modular.expect
new file mode 100644
index 0000000..6f8e4d4
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.modular.expect
@@ -0,0 +1,43 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method main() → dynamic async {
+ await self::returnsString();
+ await self::returnsFutureOrString();
+ await self::returnsAwaitFutureOrString();
+ await self::returnsFutureString();
+ await self::returnsAwaitFutureString();
+ await self::returnsObject();
+ await self::returnsFutureOrObject();
+ await self::returnsAwaitFutureOrObject();
+ await self::returnsFutureObject();
+ await self::returnsAwaitFutureObject();
+}
+static method returnsString() → asy::Future<core::String> async
+ return "a";
+static method returnsFutureOrString() → asy::Future<core::String> async
+ return self::getFutureOr<core::String>("a");
+static method returnsAwaitFutureOrString() → asy::Future<core::String> async
+ return await self::getFutureOr<core::String>("a");
+static method returnsFutureString() → asy::Future<core::String> async
+ return self::getFuture<core::String>("a");
+static method returnsAwaitFutureString() → FutureOr<core::String> async
+ return await self::getFuture<core::String>("a");
+static method returnsObject() → asy::Future<core::Object> async
+ return new core::Object::•();
+static method returnsFutureOrObject() → asy::Future<core::Object> async
+ return self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> async
+ return await self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsFutureObject() → asy::Future<core::Object> async
+ return self::getFuture<core::Object>(new core::Object::•());
+static method returnsAwaitFutureObject() → FutureOr<core::Object> async
+ return await self::getFuture<core::Object>(new core::Object::•());
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> async
+ return v;
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> async
+ return v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.outline.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.outline.expect
new file mode 100644
index 0000000..98b26fc
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method main() → dynamic async
+ ;
+static method returnsString() → asy::Future<core::String> async
+ ;
+static method returnsFutureOrString() → asy::Future<core::String> async
+ ;
+static method returnsAwaitFutureOrString() → asy::Future<core::String> async
+ ;
+static method returnsFutureString() → asy::Future<core::String> async
+ ;
+static method returnsAwaitFutureString() → FutureOr<core::String> async
+ ;
+static method returnsObject() → asy::Future<core::Object> async
+ ;
+static method returnsFutureOrObject() → asy::Future<core::Object> async
+ ;
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> async
+ ;
+static method returnsFutureObject() → asy::Future<core::Object> async
+ ;
+static method returnsAwaitFutureObject() → FutureOr<core::Object> async
+ ;
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> async
+ ;
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> async
+ ;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.transformed.expect
new file mode 100644
index 0000000..3100e06
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.transformed.expect
@@ -0,0 +1,386 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+static method main() → dynamic /* originally async */ {
+ final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
+ core::bool* :is_sync = false;
+ dynamic :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ [yield] let dynamic #t1 = asy::_awaitHelper(self::returnsString(), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::String>(:result);
+ [yield] let dynamic #t2 = asy::_awaitHelper(self::returnsFutureOrString(), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::String>(:result);
+ [yield] let dynamic #t3 = asy::_awaitHelper(self::returnsAwaitFutureOrString(), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::String>(:result);
+ [yield] let dynamic #t4 = asy::_awaitHelper(self::returnsFutureString(), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::String>(:result);
+ [yield] let dynamic #t5 = asy::_awaitHelper(self::returnsAwaitFutureString(), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::String>(:result);
+ [yield] let dynamic #t6 = asy::_awaitHelper(self::returnsObject(), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::Object>(:result);
+ [yield] let dynamic #t7 = asy::_awaitHelper(self::returnsFutureOrObject(), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::Object>(:result);
+ [yield] let dynamic #t8 = asy::_awaitHelper(self::returnsAwaitFutureOrObject(), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::Object>(:result);
+ [yield] let dynamic #t9 = asy::_awaitHelper(self::returnsFutureObject(), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::Object>(:result);
+ [yield] let dynamic #t10 = asy::_awaitHelper(self::returnsAwaitFutureObject(), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::Object>(:result);
+ }
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method returnsString() → asy::Future<core::String> /* originally async */ {
+ final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+ core::bool* :is_sync = false;
+ core::String? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ :return_value = "a";
+ break #L2;
+ }
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method returnsFutureOrString() → asy::Future<core::String> /* originally async */ {
+ final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+ core::bool* :is_sync = false;
+ FutureOr<core::String>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L3:
+ {
+ :return_value = self::getFutureOr<core::String>("a");
+ break #L3;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method returnsAwaitFutureOrString() → asy::Future<core::String> /* originally async */ {
+ final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+ core::bool* :is_sync = false;
+ core::String? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L4:
+ {
+ [yield] let dynamic #t11 = asy::_awaitHelper(self::getFutureOr<core::String>("a"), :async_op_then, :async_op_error, :async_op) in null;
+ :return_value = _in::unsafeCast<core::String>(:result);
+ break #L4;
+ }
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method returnsFutureString() → asy::Future<core::String> /* originally async */ {
+ final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+ core::bool* :is_sync = false;
+ FutureOr<core::String>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L5:
+ {
+ :return_value = self::getFuture<core::String>("a");
+ break #L5;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method returnsAwaitFutureString() → FutureOr<core::String> /* originally async */ {
+ final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+ core::bool* :is_sync = false;
+ core::String? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L6:
+ {
+ [yield] let dynamic #t12 = asy::_awaitHelper(self::getFuture<core::String>("a"), :async_op_then, :async_op_error, :async_op) in null;
+ :return_value = _in::unsafeCast<core::String>(:result);
+ break #L6;
+ }
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method returnsObject() → asy::Future<core::Object> /* originally async */ {
+ final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+ core::bool* :is_sync = false;
+ FutureOr<core::Object>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L7:
+ {
+ :return_value = new core::Object::•();
+ break #L7;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method returnsFutureOrObject() → asy::Future<core::Object> /* originally async */ {
+ final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+ core::bool* :is_sync = false;
+ FutureOr<core::Object>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L8:
+ {
+ :return_value = self::getFutureOr<core::Object>(new core::Object::•());
+ break #L8;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> /* originally async */ {
+ final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+ core::bool* :is_sync = false;
+ FutureOr<core::Object>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L9:
+ {
+ [yield] let dynamic #t13 = asy::_awaitHelper(self::getFutureOr<core::Object>(new core::Object::•()), :async_op_then, :async_op_error, :async_op) in null;
+ :return_value = _in::unsafeCast<core::Object>(:result);
+ break #L9;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method returnsFutureObject() → asy::Future<core::Object> /* originally async */ {
+ final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+ core::bool* :is_sync = false;
+ FutureOr<core::Object>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L10:
+ {
+ :return_value = self::getFuture<core::Object>(new core::Object::•());
+ break #L10;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method returnsAwaitFutureObject() → FutureOr<core::Object> /* originally async */ {
+ final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+ core::bool* :is_sync = false;
+ FutureOr<core::Object>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L11:
+ {
+ [yield] let dynamic #t14 = asy::_awaitHelper(self::getFuture<core::Object>(new core::Object::•()), :async_op_then, :async_op_error, :async_op) in null;
+ :return_value = _in::unsafeCast<core::Object>(:result);
+ break #L11;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> /* originally async */ {
+ final asy::_Future<self::getFutureOr::T%> :async_future = new asy::_Future::•<self::getFutureOr::T%>();
+ core::bool* :is_sync = false;
+ FutureOr<self::getFutureOr::T%>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L12:
+ {
+ :return_value = v;
+ break #L12;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> /* originally async */ {
+ final asy::_Future<self::getFuture::T%> :async_future = new asy::_Future::•<self::getFuture::T%>();
+ core::bool* :is_sync = false;
+ FutureOr<self::getFuture::T%>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L13:
+ {
+ :return_value = v;
+ break #L13;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
diff --git a/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect
index c05a8b5..7e77550 100644
--- a/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect
@@ -13,7 +13,7 @@
static method foo() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -24,7 +24,7 @@
{
invalid-type x;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
index 758329d..ef502e2 100644
--- a/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
@@ -30,7 +30,7 @@
static method main() → void /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -62,7 +62,7 @@
throw "Expected '${expected}' but got '${actual}'";
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/await.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await.dart.weak.transformed.expect
index 6107389..7fd936b 100644
--- a/pkg/front_end/testcases/general/await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -20,7 +20,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper("Hello, World!", :async_op_then, :async_op_error, :async_op) in null;
core::print(_in::unsafeCast<core::String*>(:result));
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
index 087766ec..22900f0 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
@@ -59,7 +59,7 @@
static method staticMembers() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -100,7 +100,7 @@
core::num* e = _in::unsafeCast<core::int*>(:async_temporary_5).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
self::expect(5, e);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -115,7 +115,7 @@
static method topLevelMembers() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -151,7 +151,7 @@
core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
self::expect(5, e);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -166,7 +166,7 @@
static method instanceMembers() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -203,7 +203,7 @@
core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
self::expect(5, e);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -218,7 +218,7 @@
static method others() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -255,7 +255,7 @@
core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
self::expect(2, e);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -270,7 +270,7 @@
static method conditionals() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -327,7 +327,7 @@
on dynamic catch(final dynamic e) {
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -342,7 +342,7 @@
static method asserts() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -400,7 +400,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -415,7 +415,7 @@
static method controlFlow() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -681,7 +681,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -758,7 +758,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -785,7 +785,7 @@
:result;
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect
index 0372529..3dce525 100644
--- a/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect
@@ -13,7 +13,7 @@
method m() → asy::Future<core::List<core::int*>*>* /* originally async */ {
final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
core::bool* :is_sync = false;
- FutureOr<core::List<core::int*>*>* :return_value;
+ core::List<core::int*>? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -29,7 +29,7 @@
:return_value = block {} =>#t1;
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -44,7 +44,7 @@
method _m() → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -56,7 +56,7 @@
:return_value = 42;
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -82,7 +82,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -95,7 +95,7 @@
[yield] let dynamic #t3 = asy::_awaitHelper(new self::C::•().{self::C::m}(){() →* asy::Future<core::List<core::int*>*>*}, :async_op_then, :async_op_error, :async_op) in null;
self::expect(42, _in::unsafeCast<core::List<core::int*>*>(:result).{core::Iterable::first}{core::int*});
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect b/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect
index 3d71e92..1345153 100644
--- a/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
static method returnsString() → FutureOr<core::String*>* /* originally async */ {
final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
core::bool* :is_sync = false;
- FutureOr<core::String*>* :return_value;
+ core::String? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -24,7 +24,7 @@
:return_value = "oh no";
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect b/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
index 85541c5..8f45939 100644
--- a/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
@@ -43,7 +43,7 @@
static method f1() → asy::Future<core::List<core::Object*>*>* /* originally async */ {
final asy::_Future<core::List<core::Object*>*>* :async_future = new asy::_Future::•<core::List<core::Object*>*>();
core::bool* :is_sync = false;
- FutureOr<core::List<core::Object*>*>* :return_value;
+ core::List<core::Object*>? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -55,7 +55,7 @@
:return_value = core::_GrowableList::_literal1<core::Object*>(1);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -72,7 +72,7 @@
static method f3() → asy::Future<core::Object*>* /* originally async */ {
final asy::_Future<core::Object*>* :async_future = new asy::_Future::•<core::Object*>();
core::bool* :is_sync = false;
- FutureOr<core::Object*>* :return_value;
+ core::Object? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -84,7 +84,7 @@
:return_value = 3;
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -99,7 +99,7 @@
static method foo() → asy::Future<self::X*>* /* originally async */ {
final asy::_Future<self::X*>* :async_future = new asy::_Future::•<self::X*>();
core::bool* :is_sync = false;
- FutureOr<self::X*>* :return_value;
+ self::X? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -120,7 +120,7 @@
:return_value = new self::X::•(_in::unsafeCast<self::Y*>(:async_temporary_0), _in::unsafeCast<core::Object*>(:result));
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -135,7 +135,7 @@
static method main() → asy::Future<void>* /* originally async */ {
final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>* :return_value;
+ void :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -148,7 +148,7 @@
[yield] let dynamic #t4 = asy::_awaitHelper(self::foo(), :async_op_then, :async_op_error, :async_op) in null;
core::print(_in::unsafeCast<self::X*>(:result));
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect b/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect
index 0a550d4..5c69330 100644
--- a/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -24,7 +24,7 @@
[yield] let dynamic #t2 = asy::_awaitHelper(LoadLibrary(lib), :async_op_then, :async_op_error, :async_op) in null;
def::m(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect
index 59854bd..e74ebe2 100644
--- a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect
@@ -1946,7 +1946,7 @@
static method testForElementErrors(core::Map<core::int*, core::int*>* map, core::List<core::int*>* list) → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -2481,7 +2481,7 @@
#t293.{core::Map::[]=}{Invariant}("baz", null){(core::String*, core::int*) →* void};
} =>#t293;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect
index d223493..cd22de9 100644
--- a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect
@@ -19,7 +19,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -60,7 +60,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.expect b/pkg/front_end/testcases/general/external_import.dart.weak.expect
index 0d7662f..5e7e2df 100644
--- a/pkg/front_end/testcases/general/external_import.dart.weak.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.weak.expect
@@ -37,5 +37,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///external_import.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect b/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect
index 0d7662f..5e7e2df 100644
--- a/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect
@@ -37,5 +37,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///external_import.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect b/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect
index 0d7662f..5e7e2df 100644
--- a/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect
@@ -37,5 +37,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///external_import.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect b/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect
index cae05ae..946e531 100644
--- a/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect
@@ -116,7 +116,7 @@
method test(covariant-by-class asy::Future<self::Response<core::String*>*>* fetch) → asy::Future<core::String*>* /* originally async */ {
final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
core::bool* :is_sync = false;
- FutureOr<core::String*>* :return_value;
+ core::String? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -146,7 +146,7 @@
:return_value = result;
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -185,7 +185,7 @@
method test(covariant-by-class asy::Future<self::PagingResponse<core::String*>*>* fetch) → asy::Future<core::String*>* /* originally async */ {
final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
core::bool* :is_sync = false;
- FutureOr<core::String*>* :return_value;
+ core::String? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -215,7 +215,7 @@
:return_value = result;
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect b/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect
index d6d5aa0..f0fb90b 100644
--- a/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect
@@ -45,7 +45,7 @@
static method returnClass() → self::Class* /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -57,7 +57,7 @@
:return_value = new self::Class::•();
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -72,7 +72,7 @@
static method returnFutureClass() → asy::Future<self::Class*>* /* originally async */ {
final asy::_Future<self::Class*>* :async_future = new asy::_Future::•<self::Class*>();
core::bool* :is_sync = false;
- FutureOr<self::Class*>* :return_value;
+ self::Class? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -84,7 +84,7 @@
:return_value = new self::Class::•();
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -99,7 +99,7 @@
static method returnFutureOrClass() → FutureOr<self::Class*>* /* originally async */ {
final asy::_Future<self::Class*>* :async_future = new asy::_Future::•<self::Class*>();
core::bool* :is_sync = false;
- FutureOr<self::Class*>* :return_value;
+ self::Class? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -111,7 +111,7 @@
:return_value = new self::Class::•();
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -369,7 +369,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -404,7 +404,7 @@
[yield] let dynamic #t12 = asy::_awaitHelper(self::returnFutureOrClassFromFutureOrClass(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<self::Class*>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect
index b9327a2..ae34a36 100644
--- a/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect
@@ -27,7 +27,7 @@
function f2() → invalid-type /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -36,7 +36,7 @@
try {
#L1:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect
index ba98fca..be46445 100644
--- a/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect
@@ -17,7 +17,7 @@
static method test(self::A<core::String> a) → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
final core::String? x = _in::unsafeCast<core::String?>(:result);
self::bar(x);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect b/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect
index e545ab0..983f3d4 100644
--- a/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
method _foo() → void /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -25,7 +25,7 @@
_in::unsafeCast<Null>(:result);
core::print("hello");
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
index 3d879b8..3c53c2b 100644
--- a/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
method foo(dynamic x) → asy::Future<void>* /* originally async */ {
final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>* :return_value;
+ void :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -20,7 +20,7 @@
try {
#L1:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -50,7 +50,7 @@
method bar(dynamic x) → asy::Future<void>* /* originally async */ {
final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>* :return_value;
+ void :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
try {
#L2:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -85,7 +85,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -105,7 +105,7 @@
:return_value = core::_GrowableList::_literal2<asy::Future<void>*>(_in::unsafeCast<asy::Future<void>*>(:async_temporary_1), _in::unsafeCast<self::B*>(:async_temporary_0).{self::B::bar}(_in::unsafeCast<Null>(:result)){(dynamic) →* asy::Future<void>*});
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect b/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect
index f6ea477..99d4140 100644
--- a/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect
@@ -37,7 +37,7 @@
static method returnFutureDynamic() → asy::Future<dynamic>* /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -49,7 +49,7 @@
:return_value = new self::Class::•();
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -64,7 +64,7 @@
static method returnFutureClass() → asy::Future<self::Class*>* /* originally async */ {
final asy::_Future<self::Class*>* :async_future = new asy::_Future::•<self::Class*>();
core::bool* :is_sync = false;
- FutureOr<self::Class*>* :return_value;
+ self::Class? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -76,7 +76,7 @@
:return_value = new self::Class::•();
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -169,7 +169,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -206,7 +206,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect
index e955e1e..1bb3512 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect
@@ -4,7 +4,7 @@
static method whatever() → dynamic /* originally async */ {
final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
dart.core::int* :await_jump_var = 0;
@@ -19,7 +19,7 @@
:return_value = "hello";
break #L1;
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -56,7 +56,7 @@
static method main() → dynamic /* originally async */ {
final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
dart.core::int* :await_jump_var = 0;
@@ -70,7 +70,7 @@
:result;
dart.core::print(#C2);
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect
index 4f65073..6a2982c 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect
@@ -4,7 +4,7 @@
static method whatever() → dynamic /* originally async */ {
final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
dart.core::int* :await_jump_var = 0;
@@ -19,7 +19,7 @@
:return_value = "hello";
break #L1;
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -56,7 +56,7 @@
static method main() → dynamic /* originally async */ {
final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
dart.core::int* :await_jump_var = 0;
@@ -71,7 +71,7 @@
dart.core::print(#C2);
dart.core::print("Done");
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect
index 5d54f1b..9d83b08 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect
@@ -22,7 +22,7 @@
static method main() → dynamic /* originally async */ {
final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
dart.core::int* :await_jump_var = 0;
@@ -36,7 +36,7 @@
:result;
dart.core::print(#C2);
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -51,7 +51,7 @@
static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
dart.core::int* :await_jump_var = 0;
@@ -66,7 +66,7 @@
:return_value = "hello";
break #L2;
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect
index d857553..d0bec69 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect
@@ -22,7 +22,7 @@
static method main() → dynamic /* originally async */ {
final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
dart.core::int* :await_jump_var = 0;
@@ -36,7 +36,7 @@
:result;
dart.core::print(#C2);
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -51,7 +51,7 @@
static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
dart.core::int* :await_jump_var = 0;
@@ -66,7 +66,7 @@
:return_value = "hello!!!";
break #L2;
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect
index 8da36e7..d9b9b9f 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect
@@ -22,7 +22,7 @@
static method main() → dynamic /* originally async */ {
final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
dart.core::int* :await_jump_var = 0;
@@ -37,7 +37,7 @@
dart.core::print(#C2);
dart.core::print("Done!");
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -52,7 +52,7 @@
static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
dart.core::int* :await_jump_var = 0;
@@ -67,7 +67,7 @@
:return_value = "hello!!!";
break #L2;
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
index cf7f401..8c98fe7 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
@@ -59,6 +59,7 @@
ffi::DynamicLibrary,
ffi::DynamicLibraryExtension,
ffi::FfiNative,
+ ffi::Finalizable,
ffi::Float,
ffi::FloatArray,
ffi::FloatPointer,
@@ -148,6 +149,7 @@
ffi::DynamicLibrary,
ffi::DynamicLibraryExtension,
ffi::FfiNative,
+ ffi::Finalizable,
ffi::Float,
ffi::FloatArray,
ffi::FloatPointer,
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
index cb6c619..820c44b 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
@@ -59,6 +59,7 @@
ffi::DynamicLibrary,
ffi::DynamicLibraryExtension,
ffi::FfiNative,
+ ffi::Finalizable,
ffi::Float,
ffi::FloatArray,
ffi::FloatPointer,
@@ -148,6 +149,7 @@
ffi::DynamicLibrary,
ffi::DynamicLibraryExtension,
ffi::FfiNative,
+ ffi::Finalizable,
ffi::Float,
ffi::FloatArray,
ffi::FloatPointer,
diff --git a/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect
index 919ede4..7072277 100644
--- a/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect
@@ -29,7 +29,7 @@
static method test() → void /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
function test0() → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -64,7 +64,7 @@
:return_value = x0;
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -340,7 +340,7 @@
[yield] let dynamic #t10 = asy::_awaitHelper(x9, :async_op_then, :async_op_error, :async_op) in null;
core::int* y9 = _in::unsafeCast<core::int*>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect
index 02f5546..d131af3 100644
--- a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
static field () →* asy::Future<core::int*>* f = () → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -18,7 +18,7 @@
:return_value = 0;
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect
index 946c0ba..33452c2 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
() →* asy::Future<core::num*>* f = () → asy::Future<core::num*>* /* originally async */ {
final asy::_Future<core::num*>* :async_future = new asy::_Future::•<core::num*>();
core::bool* :is_sync = false;
- FutureOr<core::num*>* :return_value;
+ core::num? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -29,7 +29,7 @@
break #L1;
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect
index 2f681c5..1ca076e 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -51,7 +51,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(f(){() →* asy::Future<Null>*}, :async_op_then, :async_op_error, :async_op) in null;
core::String* s = _in::unsafeCast<Null>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect
index fbf4bc7..0b66184 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -57,7 +57,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(f(){() →* asy::Stream<Null>*}.{asy::Stream::first}{asy::Future<Null>*}, :async_op_then, :async_op_error, :async_op) in null;
core::String* s = _in::unsafeCast<Null>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect
index 0b4c6aa..ef028bb 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
static method main() → asy::Future<dynamic>* /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -25,7 +25,7 @@
[yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(d as{TypeError,ForDynamic} core::int*)), :async_op_then, :async_op_error, :async_op) in null;
core::List<core::int*>* l1 = _in::unsafeCast<core::List<core::int*>*>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect
index acaf1c5..f7624fe 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect
@@ -62,7 +62,7 @@
static method f() → asy::Future<dynamic>* /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -226,7 +226,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -241,7 +241,7 @@
static method main() → asy::Future<dynamic>* /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -318,7 +318,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect
index e4fd3e1..b47ff66 100644
--- a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -83,7 +83,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect
index ab96b76..6786a24 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
asy::Future<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
:return_value = 3;
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
asy::Future<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
:return_value = 3;
break #L4;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect
index bffba5e..2f74e115 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
asy::Future<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
:return_value = 3;
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
asy::Future<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
:return_value = 3;
break #L4;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect
index 37463d1..7decc2d 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
self::MyFuture<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
:return_value = 3;
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
self::MyFuture<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
:return_value = 3;
break #L4;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect
index 90f1db4..6bc3b03 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
self::MyFuture<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
:return_value = 3;
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
self::MyFuture<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
:return_value = 3;
break #L4;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect
index 39baeba..4971cd6 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
asy::Future<core::int*>* t3 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
:return_value = 3;
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
asy::Future<core::int*>* t4 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
:return_value = 3;
break #L4;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect
index 6a2855eb..7cffed8 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
:return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
asy::Future<core::int*>* t3 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
:return_value = 3;
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
asy::Future<core::int*>* t4 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
:return_value = 3;
break #L4;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
index 204dbee..be1084c 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
:return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
index 608046f..4327ac5 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
:return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
index e32c9fb..477a406 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
:return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
index 02b3b6b..0211604 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
:return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
index e0176fc..6759525 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
:return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
index 9fb5822..877ea634 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
:return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
index bf8be62..2716550 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -60,7 +60,7 @@
:return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect
index 3145f91..955a495 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect
@@ -47,7 +47,7 @@
static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
core::bool* :is_sync = false;
- FutureOr<core::List<core::int*>*>* :return_value;
+ core::List<core::int*>? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
:return_value = core::_GrowableList::_literal1<core::int*>(3);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect
index 0bdd40c..9c426f7 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
core::bool* :is_sync = false;
- FutureOr<core::List<core::int*>*>* :return_value;
+ core::List<core::int*>? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -50,7 +50,7 @@
:return_value = core::_GrowableList::_literal1<core::int*>(3);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect
index 925b980..09a8df9 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect
@@ -47,7 +47,7 @@
static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
core::bool* :is_sync = false;
- FutureOr<core::List<core::int*>*>* :return_value;
+ core::List<core::int*>? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
:return_value = core::_GrowableList::_literal1<core::int*>(3);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect
index e0915b4..35a7372 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
core::bool* :is_sync = false;
- FutureOr<core::List<core::int*>*>* :return_value;
+ core::List<core::int*>? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -50,7 +50,7 @@
:return_value = core::_GrowableList::_literal1<core::int*>(3);
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect
index ced25c9..e617289 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect
@@ -24,7 +24,7 @@
static method foo() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -39,7 +39,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::wait<core::List<self::A*>*>(core::_GrowableList::_literal2<asy::Future<core::List<self::A*>*>*>(f1, f2)), :async_op_then, :async_op_error, :async_op) in null;
core::List<core::List<self::A*>*>* merged = _in::unsafeCast<core::List<core::List<self::A*>*>>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect
index ebe5e12..241a603 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -25,7 +25,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(self::id<FutureOr<core::String*>*>(f), :async_op_then, :async_op_error, :async_op) in null;
core::String* s = _in::unsafeCast<core::String*>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect
index edb2427..3e7e7b1 100644
--- a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect
@@ -34,7 +34,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -54,7 +54,7 @@
core::List<self::A*>* list = result;
list = result2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect
index 3715d17..9c54557 100644
--- a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
function f1() → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -21,7 +21,7 @@
:return_value = 42;
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -39,7 +39,7 @@
function f3() → asy::Future<core::int*>* /* originally async */ {
final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
core::bool* :is_sync = false;
- FutureOr<core::int*>* :return_value;
+ core::int? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -51,7 +51,7 @@
:return_value = 42;
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect
index fef5b28..8eee676 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect
@@ -58,7 +58,7 @@
method foo(covariant-by-class self::Bar::T* t) → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -97,7 +97,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -127,7 +127,7 @@
method foo(covariant-by-class self::Baz::S* t) → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -167,7 +167,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -244,7 +244,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -440,7 +440,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect
index aa020dd..dfc471b 100644
--- a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect
@@ -30,7 +30,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -122,7 +122,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect
index 2ad99fc..356e2de 100644
--- a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect
@@ -46,7 +46,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -201,7 +201,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
index 079f495..5b963bf 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
@@ -139,7 +139,7 @@
static method hest() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -178,7 +178,7 @@
:return_value = "hest";
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -193,7 +193,7 @@
static method fisk() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -250,7 +250,7 @@
function #f#set(core::Function f#param) → dynamic
return #f = f#param;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
index c43553e..c376454 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
@@ -159,7 +159,7 @@
static method hest() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -198,7 +198,7 @@
:return_value = "hest";
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -213,7 +213,7 @@
static method fisk() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -294,7 +294,7 @@
return #f = f#param;
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
index 4d771b3..e5c093e 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
@@ -25,5 +25,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
index f3903c0..de205ad 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
@@ -52,5 +52,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
index e179ab5..ec86fcc 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
@@ -25,5 +25,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect
index e179ab5..ec86fcc 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect
@@ -25,5 +25,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
index 24cfa96..77e3dbf 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
@@ -52,5 +52,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect
index dd7fa30..f82c29d 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect
@@ -33,5 +33,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect
index a16945b..d5ddd95 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect
@@ -84,5 +84,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect
index be09548..d33f1a0 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect
@@ -33,5 +33,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect
index be09548..d33f1a0 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect
@@ -33,5 +33,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect
index a83a86b..6a4db26 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect
@@ -84,5 +84,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
index 4d55755..64a9400 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
@@ -76,7 +76,7 @@
method test(covariant-by-class asy::Future<self::Response<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
core::bool* :is_sync = false;
- FutureOr<core::String>? :return_value;
+ core::String? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -106,7 +106,7 @@
:return_value = result;
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -135,7 +135,7 @@
method test(covariant-by-class asy::Future<self::PagingResponse<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
core::bool* :is_sync = false;
- FutureOr<core::String>? :return_value;
+ core::String? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
:return_value = result;
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
index 4d55755..64a9400 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
@@ -76,7 +76,7 @@
method test(covariant-by-class asy::Future<self::Response<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
core::bool* :is_sync = false;
- FutureOr<core::String>? :return_value;
+ core::String? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -106,7 +106,7 @@
:return_value = result;
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -135,7 +135,7 @@
method test(covariant-by-class asy::Future<self::PagingResponse<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
core::bool* :is_sync = false;
- FutureOr<core::String>? :return_value;
+ core::String? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
:return_value = result;
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect
index 3864109..1ecce4a 100644
--- a/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -31,7 +31,7 @@
List y = await l(); // should be a List?
^" in let core::List<dynamic>? #t2 = _in::unsafeCast<core::List<dynamic>?>(:result) in #t2 == null ?{core::List<dynamic>} #t2 as{TypeError,ForNonNullableByDefault} core::List<dynamic> : #t2{core::List<dynamic>};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect
index 18ac50d..1a6d93f 100644
--- a/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect
@@ -15,7 +15,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -31,7 +31,7 @@
List y = await l(); // should be a List?
^" in _in::unsafeCast<core::List<dynamic>?>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
index 9eb092b..ec795d3 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -20,7 +20,7 @@
core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2 == null ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
core::print(i);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
index 9eb092b..ec795d3 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -20,7 +20,7 @@
core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2 == null ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
core::print(i);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
index e3bb148..d45e990 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
@@ -85,7 +85,7 @@
(core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> /* originally async */ {
final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
core::bool* :is_sync = false;
- FutureOr<Never>? :return_value;
+ Never? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -96,7 +96,7 @@
{
throw v;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -165,7 +165,7 @@
(core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> /* originally async */ {
final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
core::bool* :is_sync = false;
- FutureOr<Never>? :return_value;
+ Never? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -176,7 +176,7 @@
{
self::throwing();
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -219,7 +219,7 @@
static method errors() → void /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -407,7 +407,7 @@
return :async_future;
};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
index dbb0ff6..90dabf3 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
@@ -86,7 +86,7 @@
(core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> /* originally async */ {
final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
core::bool* :is_sync = false;
- FutureOr<Never>? :return_value;
+ Never? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -97,7 +97,7 @@
{
throw v;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -166,7 +166,7 @@
(core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> /* originally async */ {
final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
core::bool* :is_sync = false;
- FutureOr<Never>? :return_value;
+ Never? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -177,7 +177,7 @@
{
let final Never #t5 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -220,7 +220,7 @@
static method errors() → void /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -408,7 +408,7 @@
return :async_future;
};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
index a53d4d3..ed3a3ca 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
@@ -63,7 +63,7 @@
static method getFutureBool() → asy::Future<core::bool> /* originally async */ {
final asy::_Future<core::bool> :async_future = new asy::_Future::•<core::bool>();
core::bool* :is_sync = false;
- FutureOr<core::bool>? :return_value;
+ core::bool? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -75,7 +75,7 @@
:return_value = true;
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -186,7 +186,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -390,7 +390,7 @@
return :async_future;
})(){() → asy::Future<core::bool>};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
index a53d4d3..ed3a3ca 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
@@ -63,7 +63,7 @@
static method getFutureBool() → asy::Future<core::bool> /* originally async */ {
final asy::_Future<core::bool> :async_future = new asy::_Future::•<core::bool>();
core::bool* :is_sync = false;
- FutureOr<core::bool>? :return_value;
+ core::bool? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -75,7 +75,7 @@
:return_value = true;
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -186,7 +186,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -390,7 +390,7 @@
return :async_future;
})(){() → asy::Future<core::bool>};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect
index f1dad02..8b27a53 100644
--- a/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect
@@ -145,7 +145,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -284,7 +284,7 @@
return new core::_SyncIterable::•<core::bool>(:sync_op_gen);
})(){() → core::Iterable<core::bool>};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect
index f1dad02..8b27a53 100644
--- a/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect
@@ -145,7 +145,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -284,7 +284,7 @@
return new core::_SyncIterable::•<core::bool>(:sync_op_gen);
})(){() → core::Iterable<core::bool>};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
index afdc269..995ecac 100644
--- a/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
@@ -225,7 +225,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -460,7 +460,7 @@
return :controller_stream;
})(){() → asy::Stream<core::bool>};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
index afdc269..995ecac 100644
--- a/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
@@ -225,7 +225,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -460,7 +460,7 @@
return :controller_stream;
})(){() → asy::Stream<core::bool>};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect
index 50a282e..ec6e4be 100644
--- a/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect
@@ -18,7 +18,7 @@
static method returnFutureOfVoid() → asy::Future<void> /* originally async */ {
final asy::_Future<void> :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>? :return_value;
+ void :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
try {
#L1:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -43,7 +43,7 @@
static method returnVoidAsync() → void /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -52,7 +52,7 @@
try {
#L2:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -67,7 +67,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -82,7 +82,7 @@
[yield] let dynamic #t2 = asy::_awaitHelper(self::returnVoidAsync(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -97,7 +97,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -110,7 +110,7 @@
[yield] let dynamic #t3 = asy::_awaitHelper(self::returnFutureOfVoid(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect
index 50a282e..ec6e4be 100644
--- a/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect
@@ -18,7 +18,7 @@
static method returnFutureOfVoid() → asy::Future<void> /* originally async */ {
final asy::_Future<void> :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>? :return_value;
+ void :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
try {
#L1:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -43,7 +43,7 @@
static method returnVoidAsync() → void /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -52,7 +52,7 @@
try {
#L2:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -67,7 +67,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -82,7 +82,7 @@
[yield] let dynamic #t2 = asy::_awaitHelper(self::returnVoidAsync(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -97,7 +97,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -110,7 +110,7 @@
[yield] let dynamic #t3 = asy::_awaitHelper(self::returnFutureOfVoid(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
index 5a264b1..b845eb9 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
@@ -37,7 +37,7 @@
<S extends FutureOr<core::num>>(S, FutureOr<core::num>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num>>(S s, FutureOr<core::num>t) → asy::Future<core::num> /* originally async */ {
final asy::_Future<core::num> :async_future = new asy::_Future::•<core::num>();
core::bool* :is_sync = false;
- FutureOr<core::num>? :return_value;
+ core::num? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -51,7 +51,7 @@
:return_value = _in::unsafeCast<core::num>(:result).{core::num::+}(1){(core::num) → core::num};
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
index 5a264b1..b845eb9 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
@@ -37,7 +37,7 @@
<S extends FutureOr<core::num>>(S, FutureOr<core::num>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num>>(S s, FutureOr<core::num>t) → asy::Future<core::num> /* originally async */ {
final asy::_Future<core::num> :async_future = new asy::_Future::•<core::num>();
core::bool* :is_sync = false;
- FutureOr<core::num>? :return_value;
+ core::num? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -51,7 +51,7 @@
:return_value = _in::unsafeCast<core::num>(:result).{core::num::+}(1){(core::num) → core::num};
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
index b810299..fe3f074 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
@@ -40,7 +40,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -85,7 +85,7 @@
return :async_future;
})(){() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>>} as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
index b810299..fe3f074 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
@@ -40,7 +40,7 @@
static method test() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -85,7 +85,7 @@
return :async_future;
})(){() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>>} as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
index 22760fa..ce05381 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -23,7 +23,7 @@
(dynamic _) → asy::Future<core::int?> /* originally async */ {
final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
core::bool* :is_sync = false;
- FutureOr<core::int?>? :return_value;
+ core::int? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -37,7 +37,7 @@
break #L2;
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -50,7 +50,7 @@
return :async_future;
};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
index 22760fa..ce05381 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -23,7 +23,7 @@
(dynamic _) → asy::Future<core::int?> /* originally async */ {
final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
core::bool* :is_sync = false;
- FutureOr<core::int?>? :return_value;
+ core::int? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -37,7 +37,7 @@
break #L2;
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -50,7 +50,7 @@
return :async_future;
};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
index 122e031..83b083c 100644
--- a/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -32,7 +32,7 @@
self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
} =>#t2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
index 122e031..83b083c 100644
--- a/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
@@ -15,7 +15,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -32,7 +32,7 @@
self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
} =>#t2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
index 2885cb8..5d5407b 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -126,7 +126,7 @@
static method hest() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
:return_value = "hest";
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -180,7 +180,7 @@
static method fisk() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -231,7 +231,7 @@
};
late core::Function f = #f#initializer(){() → core::Function};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
index 2885cb8..5d5407b 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -126,7 +126,7 @@
static method hest() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
:return_value = "hest";
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -180,7 +180,7 @@
static method fisk() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -231,7 +231,7 @@
};
late core::Function f = #f#initializer(){() → core::Function};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
index 2a9f5d7..765a694 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
static method allYield() → asy::Future<void> /* originally async */ {
final asy::_Future<void> :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>? :return_value;
+ void :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
[yield] let dynamic #t2 = asy::_awaitHelper(self::allYield2(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -42,7 +42,7 @@
static method allYield2() → asy::Future<void> /* originally async */ {
final asy::_Future<void> :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>? :return_value;
+ void :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
[yield] let dynamic #t4 = asy::_awaitHelper(self::allYield3(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -72,7 +72,7 @@
static method allYield3() → asy::Future<void> /* originally async */ {
final asy::_Future<void> :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>? :return_value;
+ void :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -86,7 +86,7 @@
_in::unsafeCast<core::int>(:result);
self::throwSync();
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -114,7 +114,7 @@
asy::runZonedGuarded<asy::Future<Null>>(() → asy::Future<Null> /* originally async */ {
final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
core::bool* :is_sync = false;
- FutureOr<Null>? :return_value;
+ Null :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -128,7 +128,7 @@
_in::unsafeCast<void>(:result);
completer.{asy::Completer::complete}(null){([FutureOr<void>?]) → void};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
index 2a9f5d7..765a694 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
static method allYield() → asy::Future<void> /* originally async */ {
final asy::_Future<void> :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>? :return_value;
+ void :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
[yield] let dynamic #t2 = asy::_awaitHelper(self::allYield2(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -42,7 +42,7 @@
static method allYield2() → asy::Future<void> /* originally async */ {
final asy::_Future<void> :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>? :return_value;
+ void :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
[yield] let dynamic #t4 = asy::_awaitHelper(self::allYield3(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -72,7 +72,7 @@
static method allYield3() → asy::Future<void> /* originally async */ {
final asy::_Future<void> :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>? :return_value;
+ void :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -86,7 +86,7 @@
_in::unsafeCast<core::int>(:result);
self::throwSync();
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -114,7 +114,7 @@
asy::runZonedGuarded<asy::Future<Null>>(() → asy::Future<Null> /* originally async */ {
final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
core::bool* :is_sync = false;
- FutureOr<Null>? :return_value;
+ Null :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -128,7 +128,7 @@
_in::unsafeCast<void>(:result);
completer.{asy::Completer::complete}(null){([FutureOr<void>?]) → void};
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
index d7034897..3686411 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
@@ -94,7 +94,7 @@
static method returnAsync1() → asy::Future<dynamic> /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -103,7 +103,7 @@
try {
#L1:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -118,7 +118,7 @@
static method returnAsync2() → FutureOr<dynamic> /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -127,7 +127,7 @@
try {
#L2:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -171,7 +171,7 @@
static method returnAsync4() → FutureOr<core::int?> /* originally async */ {
final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
core::bool* :is_sync = false;
- FutureOr<core::int?>? :return_value;
+ core::int? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -180,7 +180,7 @@
try {
#L4:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -195,7 +195,7 @@
static method returnAsync5() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -204,7 +204,7 @@
try {
#L5:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -246,7 +246,7 @@
static method returnAsync7() → asy::Future<core::int?> /* originally async */ {
final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
core::bool* :is_sync = false;
- FutureOr<core::int?>? :return_value;
+ core::int? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -255,7 +255,7 @@
try {
#L7:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -362,7 +362,7 @@
function returnAsync1() → asy::Future<dynamic> /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -371,7 +371,7 @@
try {
#L13:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -386,7 +386,7 @@
function returnAsync2() → FutureOr<dynamic> /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -395,7 +395,7 @@
try {
#L14:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -439,7 +439,7 @@
function returnAsync4() → FutureOr<core::int?> /* originally async */ {
final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
core::bool* :is_sync = false;
- FutureOr<core::int?>? :return_value;
+ core::int? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -448,7 +448,7 @@
try {
#L16:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -463,7 +463,7 @@
function returnAsync5() → asy::Future<Null> /* originally async */ {
final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
core::bool* :is_sync = false;
- FutureOr<Null>? :return_value;
+ Null :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -472,7 +472,7 @@
try {
#L17:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -514,7 +514,7 @@
function returnAsync7() → asy::Future<core::int?> /* originally async */ {
final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
core::bool* :is_sync = false;
- FutureOr<core::int?>? :return_value;
+ core::int? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -523,7 +523,7 @@
try {
#L19:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
index 7f20e82..081a23c 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
@@ -95,7 +95,7 @@
static method returnAsync1() → asy::Future<dynamic> /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -104,7 +104,7 @@
try {
#L1:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -119,7 +119,7 @@
static method returnAsync2() → FutureOr<dynamic> /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -128,7 +128,7 @@
try {
#L2:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -172,7 +172,7 @@
static method returnAsync4() → FutureOr<core::int?> /* originally async */ {
final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
core::bool* :is_sync = false;
- FutureOr<core::int?>? :return_value;
+ core::int? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -181,7 +181,7 @@
try {
#L4:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -196,7 +196,7 @@
static method returnAsync5() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -205,7 +205,7 @@
try {
#L5:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -247,7 +247,7 @@
static method returnAsync7() → asy::Future<core::int?> /* originally async */ {
final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
core::bool* :is_sync = false;
- FutureOr<core::int?>? :return_value;
+ core::int? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -256,7 +256,7 @@
try {
#L7:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -366,7 +366,7 @@
function returnAsync1() → asy::Future<dynamic> /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -375,7 +375,7 @@
try {
#L14:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -390,7 +390,7 @@
function returnAsync2() → FutureOr<dynamic> /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -399,7 +399,7 @@
try {
#L15:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -443,7 +443,7 @@
function returnAsync4() → FutureOr<core::int?> /* originally async */ {
final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
core::bool* :is_sync = false;
- FutureOr<core::int?>? :return_value;
+ core::int? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -452,7 +452,7 @@
try {
#L17:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -467,7 +467,7 @@
function returnAsync5() → asy::Future<Null> /* originally async */ {
final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
core::bool* :is_sync = false;
- FutureOr<Null>? :return_value;
+ Null :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -476,7 +476,7 @@
try {
#L18:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -518,7 +518,7 @@
function returnAsync7() → asy::Future<core::int?> /* originally async */ {
final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
core::bool* :is_sync = false;
- FutureOr<core::int?>? :return_value;
+ core::int? :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -527,7 +527,7 @@
try {
#L20:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect
index 96460c4..160716b 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
static method returnFutureOfVoid() → asy::Future<void>* /* originally async */ {
final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
core::bool* :is_sync = false;
- FutureOr<void>* :return_value;
+ void :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -16,7 +16,7 @@
try {
#L1:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -32,7 +32,7 @@
static method returnVoidAsync() → void /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -41,7 +41,7 @@
try {
#L2:
{}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -56,7 +56,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -73,7 +73,7 @@
[yield] let dynamic #t3 = asy::_awaitHelper(self::returnVoidAsync(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
index dcba0f6..1f53e96 100644
--- a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
return (typ::Request* r) → asy::Future<typ::Response*>* /* originally async */ {
final asy::_Future<typ::Response*>* :async_future = new asy::_Future::•<typ::Response*>();
core::bool* :is_sync = false;
- FutureOr<typ::Response*>* :return_value;
+ typ::Response? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -22,7 +22,7 @@
:return_value = new typ::Response::•();
break #L1;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect
index 7670aed..b24cb95 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect
@@ -42,5 +42,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///native_is_illegal.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect
index 7670aed..b24cb95 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect
@@ -42,5 +42,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///native_is_illegal.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect
index 7670aed..b24cb95 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect
@@ -42,5 +42,5 @@
Constructor coverage from constants:
org-dartlang-testcase:///native_is_illegal.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect
index d3211c4..b4b664d 100644
--- a/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect
@@ -116,7 +116,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -132,7 +132,7 @@
[yield] let dynamic #t2 = asy::_awaitHelper(self::f3(), :async_op_then, :async_op_error, :async_op) in null;
core::print(_in::unsafeCast<invalid-type>(:result));
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect
index 8e89457..63a99de 100644
--- a/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect
@@ -22,7 +22,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -38,7 +38,7 @@
function f_async() → core::int* /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -50,7 +50,7 @@
:return_value = 42;
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -147,7 +147,7 @@
}
}
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect
index ee407a3..9262980 100644
--- a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
+ dynamic :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
[yield] let dynamic #t13 = asy::_awaitHelper(self::lhmfun2(), :async_op_then, :async_op_error, :async_op) in null;
col::LinkedHashMap<core::int*, core::bool*>* flhm2 = _in::unsafeCast<col::LinkedHashMap<core::int*, core::bool*>*>(:result);
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
static method mapfun() → asy::Future<core::Map<core::int*, core::bool*>*>* /* originally async */ {
final asy::_Future<core::Map<core::int*, core::bool*>*>* :async_future = new asy::_Future::•<core::Map<core::int*, core::bool*>*>();
core::bool* :is_sync = false;
- FutureOr<core::Map<core::int*, core::bool*>*>* :return_value;
+ core::Map<core::int*, core::bool*>? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
:return_value = <core::int*, core::bool*>{};
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -150,7 +150,7 @@
static method setfun() → asy::Future<core::Set<core::int*>*>* /* originally async */ {
final asy::_Future<core::Set<core::int*>*>* :async_future = new asy::_Future::•<core::Set<core::int*>*>();
core::bool* :is_sync = false;
- FutureOr<core::Set<core::int*>*>* :return_value;
+ core::Set<core::int*>? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -164,7 +164,7 @@
} =>#t14;
break #L3;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -179,7 +179,7 @@
static method iterablefun() → asy::Future<core::Iterable<core::int*>*>* /* originally async */ {
final asy::_Future<core::Iterable<core::int*>*>* :async_future = new asy::_Future::•<core::Iterable<core::int*>*>();
core::bool* :is_sync = false;
- FutureOr<core::Iterable<core::int*>*>* :return_value;
+ core::Iterable<core::int*>? :return_value;
(dynamic) →* dynamic :async_op_then;
(core::Object*, core::StackTrace*) →* dynamic :async_op_error;
core::int* :await_jump_var = 0;
@@ -193,7 +193,7 @@
} =>#t15;
break #L4;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/tool/_fasta/benchmark_visualiser.html b/pkg/front_end/tool/_fasta/benchmark_visualiser.html
new file mode 100644
index 0000000..f2e509b
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/benchmark_visualiser.html
@@ -0,0 +1,78 @@
+<html>
+
+<head>
+ <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
+ <script type="text/javascript">
+ google.charts.load('current', { 'packages': ['corechart'] });
+ google.charts.setOnLoadCallback(loaded);
+
+ function drawChart() {
+ var useLogarithmic = document.getElementById('chartLog').checked;
+ try {
+ var benchmarkdata = JSON.parse(document.getElementById('jsondata').value);
+ }
+ catch (e) {
+ document.getElementById('chart_div').innerHTML = "BAD JSON #0!" + e.message;
+ return;
+ }
+ var data = new google.visualization.DataTable();
+ data.addColumn('string', 'Phase');
+
+ var countBenchmarks = benchmarkdata.benchmarkers.length;
+ for (var i = 0; i < countBenchmarks; i++) {
+ data.addColumn('number', 'Run #' + (i + 1));
+ }
+
+ var phaseCount = benchmarkdata.benchmarkers[0].phases.length;
+ for (var i = 0; i < countBenchmarks; i++) {
+ if (benchmarkdata.benchmarkers[i].phases.length != phaseCount) {
+ document.getElementById('chart_div').innerHTML = "BAD JSON #1!";
+ return;
+ }
+ }
+
+ for (var j = 0; j < phaseCount; j++) {
+ var rowArray = [];
+ rowArray.push(benchmarkdata.benchmarkers[0].phases[j].phase);
+ for (var i = 0; i < countBenchmarks; i++) {
+ rowArray.push(benchmarkdata.benchmarkers[i].phases[j].runtime);
+ if (benchmarkdata.benchmarkers[i].phases[j].phase != rowArray[0]) {
+ document.getElementById('chart_div').innerHTML = "BAD JSON #2!";
+ return;
+ }
+ }
+ data.addRow(rowArray);
+ }
+
+ if (useLogarithmic) {
+ var options = {
+ vAxis: {
+ scaleType: 'log'
+ }
+ };
+ } else {
+ var options = {};
+ }
+
+ var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
+ chart.draw(data, options);
+ }
+
+ function loaded() {
+ document.getElementById('chartitbutton').disabled = false;
+ }
+ </script>
+</head>
+
+<body>
+ <textarea id="jsondata" rows="20" cols="80"></textarea>
+ <br />
+ <input type="checkbox" id="chartLog">
+ <label for="chartLog"> Use logarithmic scale</label>
+ <br />
+
+ <button id="chartitbutton" onclick="drawChart()" disabled>Chart it!</button>
+ <div id="chart_div" style="width:1200; height:900"></div>
+</body>
+
+</html>
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 24fad8f..822fced 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -4,16 +4,23 @@
library fasta.tool.entry_points;
-import 'dart:convert' show LineSplitter, jsonDecode, jsonEncode, utf8;
+import 'dart:convert' show JsonEncoder, LineSplitter, jsonDecode, utf8;
import 'dart:io' show File, Platform, exitCode, stderr, stdin, stdout;
+import 'dart:typed_data' show Uint8List;
+
import 'package:_fe_analyzer_shared/src/util/relativize.dart'
show isWindows, relativizeUri;
+import 'package:front_end/src/api_prototype/kernel_generator.dart';
+
import 'package:front_end/src/fasta/fasta_codes.dart'
show LocatedMessage, codeInternalProblemVerificationError;
+import 'package:front_end/src/fasta/kernel/benchmarker.dart'
+ show BenchmarkPhases, Benchmarker;
+
import 'package:kernel/kernel.dart'
show CanonicalName, Library, Component, Source, loadComponentFromBytes;
@@ -55,7 +62,11 @@
import 'command_line.dart' show runProtectedFromAbort, withGlobalOptions;
-const bool summary = const bool.fromEnvironment("summary", defaultValue: false);
+const bool benchmark =
+ const bool.fromEnvironment("benchmark", defaultValue: false);
+
+const bool summary =
+ const bool.fromEnvironment("summary", defaultValue: false) || benchmark;
const int iterations = const int.fromEnvironment("iterations", defaultValue: 1);
@@ -64,13 +75,20 @@
// Timing results for each iteration
List<double> elapsedTimes = <double>[];
+ List<Benchmarker> benchmarkers = <Benchmarker>[];
for (int i = 0; i < iterations; i++) {
if (i > 0) {
print("\n\n=== Iteration ${i + 1} of $iterations");
}
- var stopwatch = new Stopwatch()..start();
- await compile(arguments);
+ Stopwatch stopwatch = new Stopwatch()..start();
+ Benchmarker? benchmarker;
+ if (benchmark) {
+ benchmarker = new Benchmarker();
+ benchmarkers.add(benchmarker);
+ }
+ await compile(arguments, benchmarker: benchmarker);
+ benchmarker?.stop();
stopwatch.stop();
elapsedTimes.add(stopwatch.elapsedMilliseconds.toDouble());
@@ -80,20 +98,47 @@
}
}
- if (summary) {
- var json = jsonEncode(<String, dynamic>{'elapsedTimes': elapsedTimes});
- print('\nSummary: $json');
- }
+ summarize(elapsedTimes, benchmarkers);
}
Future<void> outlineEntryPoint(List<String> arguments) async {
installAdditionalTargets();
+ // Timing results for each iteration
+ List<double> elapsedTimes = <double>[];
+ List<Benchmarker> benchmarkers = <Benchmarker>[];
+
for (int i = 0; i < iterations; i++) {
if (i > 0) {
- print("\n");
+ print("\n\n=== Iteration ${i + 1} of $iterations");
}
- await outline(arguments);
+ Stopwatch stopwatch = new Stopwatch()..start();
+ Benchmarker? benchmarker;
+ if (benchmark) {
+ benchmarker = new Benchmarker();
+ benchmarkers.add(benchmarker);
+ }
+ await outline(arguments, benchmarker: benchmarker);
+ benchmarker?.stop();
+ stopwatch.stop();
+
+ elapsedTimes.add(stopwatch.elapsedMilliseconds.toDouble());
+ }
+
+ summarize(elapsedTimes, benchmarkers);
+}
+
+void summarize(List<double> elapsedTimes, List<Benchmarker> benchmarkers) {
+ if (summary) {
+ Map<String, dynamic> map = <String, dynamic>{
+ 'elapsedTimes': elapsedTimes,
+ if (benchmarkers.isNotEmpty) 'benchmarkers': benchmarkers
+ };
+ JsonEncoder encoder = new JsonEncoder.withIndent(" ");
+ String json = encoder.convert(map);
+ print('\nSummary:\n\n$json\n');
+ } else {
+ assert(benchmarkers.isEmpty);
}
}
@@ -218,7 +263,8 @@
});
}
-Future<KernelTarget> outline(List<String> arguments) async {
+Future<KernelTarget> outline(List<String> arguments,
+ {Benchmarker? benchmarker}) async {
return await runProtectedFromAbort<KernelTarget>(() async {
return await withGlobalOptions("outline", arguments, true,
(CompilerContext c, _) async {
@@ -228,12 +274,14 @@
CompileTask task =
new CompileTask(c, new Ticker(isVerbose: c.options.verbose));
return await task.buildOutline(
- output: c.options.output, omitPlatform: c.options.omitPlatform);
+ output: c.options.output,
+ omitPlatform: c.options.omitPlatform,
+ benchmarker: benchmarker);
});
});
}
-Future<Uri> compile(List<String> arguments) async {
+Future<Uri> compile(List<String> arguments, {Benchmarker? benchmarker}) async {
return await runProtectedFromAbort<Uri>(() async {
return await withGlobalOptions("compile", arguments, true,
(CompilerContext c, _) async {
@@ -242,7 +290,8 @@
}
CompileTask task =
new CompileTask(c, new Ticker(isVerbose: c.options.verbose));
- return await task.compile(omitPlatform: c.options.omitPlatform);
+ return await task.compile(
+ omitPlatform: c.options.omitPlatform, benchmarker: benchmarker);
});
});
}
@@ -267,8 +316,10 @@
CompileTask(this.c, this.ticker);
- DillTarget createDillTarget(UriTranslator uriTranslator) {
- return new DillTarget(ticker, uriTranslator, c.options.target);
+ DillTarget createDillTarget(UriTranslator uriTranslator,
+ {Benchmarker? benchmarker}) {
+ return new DillTarget(ticker, uriTranslator, c.options.target,
+ benchmarker: benchmarker);
}
KernelTarget createKernelTarget(
@@ -303,8 +354,10 @@
Future<KernelTarget> buildOutline(
{Uri? output,
bool omitPlatform: false,
- bool supportAdditionalDills: true}) async {
- KernelTarget kernelTarget = await _createKernelTarget();
+ bool supportAdditionalDills: true,
+ Benchmarker? benchmarker}) async {
+ KernelTarget kernelTarget =
+ await _createKernelTarget(benchmarker: benchmarker);
BuildResult buildResult = await _buildOutline(kernelTarget,
output: output,
omitPlatform: omitPlatform,
@@ -313,10 +366,11 @@
return kernelTarget;
}
- Future<KernelTarget> _createKernelTarget() async {
+ Future<KernelTarget> _createKernelTarget({Benchmarker? benchmarker}) async {
UriTranslator uriTranslator = await c.options.getUriTranslator();
ticker.logMs("Read packages file");
- DillTarget dillTarget = createDillTarget(uriTranslator);
+ DillTarget dillTarget =
+ createDillTarget(uriTranslator, benchmarker: benchmarker);
return createKernelTarget(dillTarget, uriTranslator);
}
@@ -325,19 +379,23 @@
bool omitPlatform: false,
bool supportAdditionalDills: true}) async {
DillTarget dillTarget = kernelTarget.dillTarget;
+ Benchmarker? benchmarker = dillTarget.benchmarker;
if (supportAdditionalDills) {
+ benchmarker?.enterPhase(BenchmarkPhases.loadSDK);
Component? sdkSummary = await c.options.loadSdkSummary(null);
if (sdkSummary != null) {
dillTarget.loader.appendLibraries(sdkSummary);
}
+ benchmarker?.enterPhase(BenchmarkPhases.loadAdditionalDills);
CanonicalName nameRoot = sdkSummary?.root ?? new CanonicalName.root();
for (Component additionalDill
in await c.options.loadAdditionalDills(nameRoot)) {
dillTarget.loader.appendLibraries(additionalDill);
}
} else {
+ benchmarker?.enterPhase(BenchmarkPhases.loadSDK);
Component? sdkSummary = await c.options.loadSdkSummary(null);
if (sdkSummary != null) {
dillTarget.loader.appendLibraries(sdkSummary);
@@ -349,11 +407,13 @@
BuildResult buildResult = await kernelTarget.buildOutlines();
Component? outline = buildResult.component;
if (c.options.debugDump && output != null) {
+ benchmarker?.enterPhase(BenchmarkPhases.printComponentText);
printComponentText(outline,
libraryFilter: kernelTarget.isSourceLibraryForDebugging);
}
if (output != null) {
if (omitPlatform) {
+ benchmarker?.enterPhase(BenchmarkPhases.omitPlatform);
outline!.computeCanonicalNames();
Component userCode = new Component(
nameRoot: outline.root,
@@ -368,16 +428,21 @@
outline = userCode;
}
+ benchmarker?.enterPhase(BenchmarkPhases.writeComponent);
await writeComponentToFile(outline!, output);
ticker.logMs("Wrote outline to ${output.toFilePath()}");
}
+ benchmarker?.enterPhase(BenchmarkPhases.unknown);
return buildResult;
}
Future<Uri> compile(
- {bool omitPlatform: false, bool supportAdditionalDills: true}) async {
+ {bool omitPlatform: false,
+ bool supportAdditionalDills: true,
+ Benchmarker? benchmarker}) async {
c.options.reportNullSafetyCompilationModeInfo();
- KernelTarget kernelTarget = await _createKernelTarget();
+ KernelTarget kernelTarget =
+ await _createKernelTarget(benchmarker: benchmarker);
BuildResult buildResult = await _buildOutline(kernelTarget,
supportAdditionalDills: supportAdditionalDills);
Uri uri = c.options.output!;
@@ -387,10 +452,12 @@
buildResult.macroApplications?.close();
Component component = buildResult.component!;
if (c.options.debugDump) {
+ benchmarker?.enterPhase(BenchmarkPhases.printComponentText);
printComponentText(component,
libraryFilter: kernelTarget.isSourceLibraryForDebugging);
}
if (omitPlatform) {
+ benchmarker?.enterPhase(BenchmarkPhases.omitPlatform);
component.computeCanonicalNames();
Component userCode = new Component(
nameRoot: component.root,
@@ -405,9 +472,11 @@
component = userCode;
}
if (uri.scheme == "file") {
+ benchmarker?.enterPhase(BenchmarkPhases.writeComponent);
await writeComponentToFile(component, uri);
ticker.logMs("Wrote component to ${uri.toFilePath()}");
}
+ benchmarker?.enterPhase(BenchmarkPhases.unknown);
return uri;
}
}
@@ -415,8 +484,8 @@
/// Load the [Component] from the given [uri] and append its libraries
/// to the [dillTarget].
Component _appendDillForUri(DillTarget dillTarget, Uri uri) {
- var bytes = new File.fromUri(uri).readAsBytesSync();
- var platformComponent = loadComponentFromBytes(bytes);
+ Uint8List bytes = new File.fromUri(uri).readAsBytesSync();
+ Component platformComponent = loadComponentFromBytes(bytes);
dillTarget.loader.appendLibraries(platformComponent, byteCount: bytes.length);
return platformComponent;
}
@@ -439,7 +508,7 @@
print("Compiling ${c.options.sdkRoot} to $fullOutput");
}
- var result =
+ CompilerResult result =
await generateKernelInternal(buildSummary: true, buildComponent: true);
// ignore: unnecessary_null_comparison
if (result == null) {
diff --git a/pkg/front_end/tool/incremental_perf.dart b/pkg/front_end/tool/incremental_perf.dart
index 6b91a96..afb0e81 100644
--- a/pkg/front_end/tool/incremental_perf.dart
+++ b/pkg/front_end/tool/incremental_perf.dart
@@ -123,7 +123,7 @@
final UriTranslator uriTranslator = await processedOptions.getUriTranslator();
collector.start("Initial compilation");
- var generator = new IncrementalKernelGenerator(compilerOptions, entryUri);
+ var generator = new IncrementalKernelGenerator(compilerOptions, [entryUri]);
var compilerResult = await generator.computeDelta();
var component = compilerResult.component;
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index d59f082..d68a4ec 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -89,6 +89,9 @@
help: 'Path to output Ninja depfile. Only used in batch mode.')
..addOption('packages',
help: '.packages file to use for compilation', defaultsTo: null)
+ ..addMultiOption('source',
+ help: 'List additional source files to include into compilation.',
+ defaultsTo: const <String>[])
..addOption('target',
help: 'Target model that determines what core libraries are available',
allowed: <String>[
@@ -363,6 +366,7 @@
ProcessedOptions _processedOptions;
FileSystem _fileSystem;
Uri _mainSource;
+ List<Uri> _additionalSources;
ArgResults _options;
IncrementalCompiler _generator;
@@ -422,6 +426,8 @@
options['filesystem-scheme'], options['filesystem-root'],
allowHttp: options['enable-http-uris']);
_mainSource = resolveInputUri(entryPoint);
+ _additionalSources =
+ (options['source'] as List<String>).map(resolveInputUri).toList();
_kernelBinaryFilenameFull = _options['output-dill'] ?? '$entryPoint.dill';
_kernelBinaryFilenameIncremental = _options['output-incremental-dill'] ??
(_options['output-dill'] != null
@@ -575,6 +581,7 @@
}
results = await _runWithPrintRedirection(() => compileToKernel(
_mainSource, compilerOptions,
+ additionalSources: _additionalSources,
includePlatform: options['link-platform'],
deleteToStringPackageUris: options['delete-tostring-package-uri'],
aot: options['aot'],
@@ -809,8 +816,8 @@
}
errors.clear();
- IncrementalCompilerResult deltaProgramResult =
- await _generator.compile(entryPoint: _mainSource);
+ IncrementalCompilerResult deltaProgramResult = await _generator
+ .compile(entryPoints: [_mainSource, ..._additionalSources]);
Component deltaProgram = deltaProgramResult.component;
if (deltaProgram != null && transformer != null) {
transformer.transform(deltaProgram);
@@ -1078,7 +1085,8 @@
}
IncrementalCompiler _createGenerator(Uri initializeFromDillUri) {
- return IncrementalCompiler(_compilerOptions, _mainSource,
+ return IncrementalCompiler(
+ _compilerOptions, [_mainSource, ..._additionalSources],
initializeFromDillUri: initializeFromDillUri,
incrementalSerialization: incrementalSerialization);
}
diff --git a/pkg/frontend_server/test/frontend_server_test.dart b/pkg/frontend_server/test/frontend_server_test.dart
index 35f6315..1d7e607 100644
--- a/pkg/frontend_server/test/frontend_server_test.dart
+++ b/pkg/frontend_server/test/frontend_server_test.dart
@@ -424,7 +424,7 @@
when(generator.compile()).thenAnswer((_) =>
Future<IncrementalCompilerResult>.value(
IncrementalCompilerResult(Component())));
- when(generator.compile(entryPoint: anyNamed("entryPoint"))).thenAnswer(
+ when(generator.compile(entryPoints: anyNamed("entryPoints"))).thenAnswer(
(_) => Future<IncrementalCompilerResult>.value(
IncrementalCompilerResult(Component())));
final _MockedBinaryPrinterFactory printerFactory =
@@ -1653,6 +1653,68 @@
expect(await starter(args), 0);
});
+ test('compile multiple sources', () async {
+ final src1 = File('${tempDir.path}/src1.dart')
+ ..createSync()
+ ..writeAsStringSync("main() {}\n");
+ final src2 = File('${tempDir.path}/src2.dart')
+ ..createSync()
+ ..writeAsStringSync("entryPoint2() {}\n");
+ final src3 = File('${tempDir.path}/src3.dart')
+ ..createSync()
+ ..writeAsStringSync("entryPoint3() {}\n");
+ final packagesFile = File('${tempDir.path}/.packages')
+ ..createSync()
+ ..writeAsStringSync("\n");
+ final dillFile = File('${tempDir.path}/app.dill');
+ expect(dillFile.existsSync(), equals(false));
+ final List<String> args = <String>[
+ '--sdk-root=${sdkRoot.toFilePath()}',
+ '--incremental',
+ '--packages=${packagesFile.path}',
+ '--source=${src2.path}',
+ '--source=${src3.path}',
+ '--platform=${platformKernel.path}',
+ '--output-dill=${dillFile.path}'
+ ];
+
+ final StreamController<List<int>> inputStreamController =
+ StreamController<List<int>>();
+ final StreamController<List<int>> stdoutStreamController =
+ StreamController<List<int>>();
+ final IOSink ioSink = IOSink(stdoutStreamController.sink);
+ StreamController<Result> receivedResults = StreamController<Result>();
+
+ final outputParser = OutputParser(receivedResults);
+ stdoutStreamController.stream
+ .transform(utf8.decoder)
+ .transform(const LineSplitter())
+ .listen(outputParser.listener);
+
+ Future<int> result =
+ starter(args, input: inputStreamController.stream, output: ioSink);
+ inputStreamController.add('compile ${src1.uri}\n'.codeUnits);
+ receivedResults.stream.listen((Result compiledResult) {
+ CompilationResult result =
+ CompilationResult.parse(compiledResult.status);
+ expect(dillFile.existsSync(), equals(true));
+ expect(result.filename, dillFile.path);
+ expect(result.errorsCount, 0);
+
+ final component = loadComponentFromBinary(dillFile.path);
+ // Contains (at least) the 3 files we want.
+ final srcUris = {src1.uri, src2.uri, src3.uri};
+ expect(
+ component.libraries
+ .where((lib) => srcUris.contains(lib.fileUri))
+ .length,
+ srcUris.length);
+ inputStreamController.add('quit\n'.codeUnits);
+ });
+ expect(await result, 0);
+ inputStreamController.close();
+ });
+
group('http uris', () {
var host = 'localhost';
File dillFile;
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index feaa794..4dc523e 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -164,6 +164,9 @@
late final Procedure completeOnAsyncReturn =
index.getTopLevelProcedure('dart:async', '_completeOnAsyncReturn');
+ late final Procedure completeWithNoFutureOnAsyncReturn = index
+ .getTopLevelProcedure('dart:async', '_completeWithNoFutureOnAsyncReturn');
+
late final Procedure completeOnAsyncError =
index.getTopLevelProcedure('dart:async', '_completeOnAsyncError');
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index ad89d1f..c0375c2 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -1347,6 +1347,18 @@
VariableDeclaration? asyncFutureVariable;
VariableDeclaration? isSyncVariable;
+ // In general an async functions such as
+ //
+ // Future<X> foo() async { return <expr>; }
+ //
+ // can return as `<expr>` either X or Future<X>, i.e. it can return
+ // FutureOr<X>
+ //
+ // If we know it doesn't return any object of type `Future`, we can optimize
+ // the future completion process by avoiding some expensive `is Future<T>`
+ // type checks on the returned value.
+ late bool canReturnFuture;
+
AsyncFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
StatefulStaticTypeContext staticTypeContext)
: super(helper, enclosingFunction, staticTypeContext);
@@ -1385,13 +1397,22 @@
type: helper.coreTypes.boolLegacyRawType);
statements.add(isSyncVariable!);
- // asy::FutureOr<dynamic>* :return_value;
+ // asy::FutureOr<T>* :return_value;
returnVariable = VariableDeclaration(ContinuationVariables.returnValue,
type: returnType);
statements.add(returnVariable!);
+ canReturnFuture = false;
+
setupAsyncContinuations(statements);
+ // If we could prove the function doesn't return a `Future` we change the
+ // type of `:return_value`.
+ if (!canReturnFuture) {
+ returnVariable!.type =
+ valueType.withDeclaredNullability(Nullability.nullable);
+ }
+
// :async_op();
final startStatement = ExpressionStatement(LocalFunctionInvocation(
nestedClosureVariable, Arguments([]),
@@ -1439,7 +1460,9 @@
return Block(<Statement>[
body,
ExpressionStatement(StaticInvocation(
- helper.completeOnAsyncReturn,
+ canReturnFuture
+ ? helper.completeOnAsyncReturn
+ : helper.completeWithNoFutureOnAsyncReturn,
Arguments([
VariableGet(asyncFutureVariable!),
VariableGet(returnVariable!),
@@ -1452,14 +1475,47 @@
@override
TreeNode visitReturnStatement(
ReturnStatement node, TreeNode? removalSentinel) {
- var expr = node.expression == null
- ? new NullLiteral()
+ final expression = node.expression;
+ if (expression != null && !canReturnFuture) {
+ final returnedType = staticTypeContext.getExpressionType(expression);
+ canReturnFuture = _canHoldFutureObject(returnedType);
+ }
+
+ final transformedExpression = node.expression == null
+ ? NullLiteral()
: expressionRewriter!.rewrite(node.expression!, statements);
- statements.add(new ExpressionStatement(
- new VariableSet(returnVariable!, expr)..fileOffset = node.fileOffset));
- statements.add(new BreakStatement(labeledBody!));
+ statements.add(ExpressionStatement(
+ VariableSet(returnVariable!, transformedExpression)
+ ..fileOffset = node.fileOffset));
+ statements.add(BreakStatement(labeledBody!));
return removalSentinel ?? EmptyStatement();
}
+
+ bool _canHoldFutureObject(DartType type) {
+ // Any supertype or subtype of `FutureOr` may hold a `Future` object.
+ final env = staticTypeContext.typeEnvironment;
+
+ if (type is TypeParameterType) {
+ type = type.parameter.defaultType;
+ }
+
+ if (type is FutureOrType) return true;
+
+ // Any supertype of Future (which includes Future/Object/dynamic) can hold
+ // Future objects.
+ if (env.isSubtypeOf(
+ helper.futureType, type, SubtypeCheckMode.ignoringNullabilities)) {
+ return true;
+ }
+
+ // Any subtype of Future (which includes Future/_Future and any user-defined
+ // implementations) can hold Future objects.
+ if (env.isSubtypeOf(
+ type, helper.futureType, SubtypeCheckMode.ignoringNullabilities)) {
+ return true;
+ }
+ return false;
+ }
}
class HelperNodes {
@@ -1476,6 +1532,7 @@
final Procedure asyncThenWrapper;
final Procedure awaitHelper;
final Procedure completeOnAsyncReturn;
+ final Procedure completeWithNoFutureOnAsyncReturn;
final Procedure completeOnAsyncError;
final Library coreLibrary;
final CoreTypes coreTypes;
@@ -1496,6 +1553,7 @@
final Member syncIteratorYieldEachIterable;
final Class boolClass;
final Procedure unsafeCast;
+ final DartType futureType;
bool productMode;
@@ -1513,6 +1571,7 @@
this.asyncThenWrapper,
this.awaitHelper,
this.completeOnAsyncReturn,
+ this.completeWithNoFutureOnAsyncReturn,
this.completeOnAsyncError,
this.coreLibrary,
this.coreTypes,
@@ -1533,7 +1592,9 @@
this.syncIteratorYieldEachIterable,
this.boolClass,
this.productMode,
- this.unsafeCast);
+ this.unsafeCast)
+ : futureType = InterfaceType(
+ futureClass, Nullability.nonNullable, [DynamicType()]);
factory HelperNodes.fromCoreTypes(CoreTypes coreTypes, bool productMode) {
return new HelperNodes._(
@@ -1550,6 +1611,7 @@
coreTypes.asyncThenWrapperHelperProcedure,
coreTypes.awaitHelperProcedure,
coreTypes.completeOnAsyncReturn,
+ coreTypes.completeWithNoFutureOnAsyncReturn,
coreTypes.completeOnAsyncError,
coreTypes.coreLibrary,
coreTypes,
diff --git a/pkg/vm/analysis_options.yaml b/pkg/vm/analysis_options.yaml
index 76886bd..4aaf9c5 100644
--- a/pkg/vm/analysis_options.yaml
+++ b/pkg/vm/analysis_options.yaml
@@ -4,5 +4,4 @@
analyzer:
exclude:
- - testcases/**
- tool/**
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 43240f8..8e3f752 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -324,16 +324,16 @@
result.generator = new IncrementalCompiler.forExpressionCompilationOnly(
component,
result.options,
- component.mainMethod!.enclosingLibrary.fileUri);
+ [component.mainMethod!.enclosingLibrary.fileUri]);
return result;
}
@override
Future<CompilerResult> compileInternal(Uri script) async {
- final generator = this.generator ??= IncrementalCompiler(options, script);
+ final generator = this.generator ??= IncrementalCompiler(options, [script]);
errorsPlain.clear();
errorsColorized.clear();
- final compilerResult = await generator.compile(entryPoint: script);
+ final compilerResult = await generator.compile(entryPoints: [script]);
final component = compilerResult.component;
return new CompilerResult(component, const {},
compilerResult.classHierarchy, compilerResult.coreTypes);
@@ -367,7 +367,7 @@
new BinaryPrinter(sink).writeComponentFile(fullComponent);
sink.close();
- clone.generator = new IncrementalCompiler(options, generator.entryPoint,
+ clone.generator = new IncrementalCompiler(options, generator.entryPoints,
initializeFromDillUri: Uri.file(filename));
return clone;
}
diff --git a/pkg/vm/lib/incremental_compiler.dart b/pkg/vm/lib/incremental_compiler.dart
index 3794fbf..fdf6e5c 100644
--- a/pkg/vm/lib/incremental_compiler.dart
+++ b/pkg/vm/lib/incremental_compiler.dart
@@ -29,45 +29,44 @@
bool initialized = false;
bool fullComponent = false;
Uri? initializeFromDillUri;
- Uri _entryPoint;
+ List<Uri> _entryPoints;
final bool forExpressionCompilationOnly;
- Uri get entryPoint => _entryPoint;
+ List<Uri> get entryPoints => _entryPoints;
IncrementalKernelGenerator get generator => _generator;
IncrementalCompilerResult? get lastKnownGoodResult => _lastKnownGood;
- IncrementalCompiler(this._compilerOptions, this._entryPoint,
+ IncrementalCompiler(this._compilerOptions, this._entryPoints,
{this.initializeFromDillUri, bool incrementalSerialization: true})
: forExpressionCompilationOnly = false {
if (incrementalSerialization) {
incrementalSerializer = new IncrementalSerializer();
}
- _generator = new IncrementalKernelGenerator(_compilerOptions, _entryPoint,
+ _generator = new IncrementalKernelGenerator(_compilerOptions, _entryPoints,
initializeFromDillUri, false, incrementalSerializer);
_pendingDeltas = <IncrementalCompilerResult>[];
}
IncrementalCompiler.forExpressionCompilationOnly(
- Component component, this._compilerOptions, this._entryPoint)
+ Component component, this._compilerOptions, this._entryPoints)
: forExpressionCompilationOnly = true {
_generator = new IncrementalKernelGenerator.forExpressionCompilationOnly(
- _compilerOptions, _entryPoint, component);
+ _compilerOptions, _entryPoints, component);
_pendingDeltas = <IncrementalCompilerResult>[];
}
/// Recompiles invalidated files, produces incremental component.
///
- /// If [entryPoint] is specified, that points to new entry point for the
- /// compilation. Otherwise, previously set entryPoint is used.
- Future<IncrementalCompilerResult> compile({Uri? entryPoint}) async {
+ /// If [entryPoints] is specified, that points to the new list of entry
+ /// points for the compilation. Otherwise, previously set entryPoints are
+ /// used.
+ Future<IncrementalCompilerResult> compile({List<Uri>? entryPoints}) async {
final task = new TimelineTask();
try {
task.start("IncrementalCompiler.compile");
- _entryPoint = entryPoint ?? _entryPoint;
- List<Uri>? entryPoints;
- if (entryPoint != null) entryPoints = [entryPoint];
+ _entryPoints = entryPoints ?? _entryPoints;
IncrementalCompilerResult compilerResult = await _generator.computeDelta(
- entryPoints: entryPoints, fullComponent: fullComponent);
+ entryPoints: _entryPoints, fullComponent: fullComponent);
initialized = true;
fullComponent = false;
_pendingDeltas.add(compilerResult);
@@ -176,8 +175,8 @@
_lastKnownGood?.component.relink();
_generator = new IncrementalKernelGenerator.fromComponent(_compilerOptions,
- _entryPoint, _lastKnownGood?.component, false, incrementalSerializer);
- await _generator.computeDelta(entryPoints: [_entryPoint]);
+ _entryPoints, _lastKnownGood?.component, false, incrementalSerializer);
+ await _generator.computeDelta(entryPoints: _entryPoints);
}
/// This tells incremental compiler that it needs rescan [uri] file during
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 76a0f85..e77ba6b 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -97,6 +97,9 @@
' If multi-root file system is used, the input script and .packages file should be specified using URI.');
args.addOption('filesystem-scheme',
help: 'The URI scheme for the multi-root virtual filesystem.');
+ args.addMultiOption('source',
+ help: 'List additional source files to include into compilation.',
+ defaultsTo: const <String>[]);
args.addOption('target',
help: 'Target model that determines what core libraries are available',
allowed: <String>['vm', 'flutter', 'flutter_runner', 'dart_runner'],
@@ -203,6 +206,7 @@
final bool treeShakeWriteOnlyFields = options['tree-shake-write-only-fields'];
final List<String>? experimentalFlags = options['enable-experiment'];
final Map<String, String> environmentDefines = {};
+ final List<String> sources = options['source'];
if (!parseCommandLineDefines(options['define'], environmentDefines, usage)) {
return badUsageExitCode;
@@ -248,6 +252,8 @@
mainUri = await convertToPackageUri(fileSystem, mainUri, packagesUri);
}
+ final List<Uri> additionalSources = sources.map(resolveInputUri).toList();
+
final verbosity = Verbosity.parseArgument(options['verbosity']);
final errorPrinter = new ErrorPrinter(verbosity);
final errorDetector =
@@ -285,6 +291,7 @@
}
final results = await compileToKernel(mainUri, compilerOptions,
+ additionalSources: additionalSources,
includePlatform: additionalDills.isNotEmpty,
deleteToStringPackageUris: options['delete-tostring-package-uri'],
aot: aot,
@@ -354,7 +361,8 @@
///
Future<KernelCompilationResults> compileToKernel(
Uri source, CompilerOptions options,
- {bool includePlatform: false,
+ {List<Uri> additionalSources: const <Uri>[],
+ bool includePlatform: false,
List<String> deleteToStringPackageUris: const <String>[],
bool aot: false,
bool useGlobalTypeFlowAnalysis: false,
@@ -379,7 +387,8 @@
compilerResult =
await loadKernel(options.fileSystem, resolveInputUri(fromDillFile));
} else {
- compilerResult = await kernelForProgram(source, options);
+ compilerResult = await kernelForProgram(source, options,
+ additionalSources: additionalSources);
}
final Component? component = compilerResult?.component;
Iterable<Uri>? compiledSources = component?.uriToSource.keys;
diff --git a/pkg/vm/lib/transformations/ffi/common.dart b/pkg/vm/lib/transformations/ffi/common.dart
index c23bddb..5c20ebf 100644
--- a/pkg/vm/lib/transformations/ffi/common.dart
+++ b/pkg/vm/lib/transformations/ffi/common.dart
@@ -252,6 +252,7 @@
final Procedure asFunctionTearoff;
final Procedure lookupFunctionTearoff;
final Procedure getNativeFieldFunction;
+ final Class finalizableClass;
final Procedure reachabilityFenceFunction;
final Procedure checkAbiSpecificIntegerMappingFunction;
@@ -479,6 +480,7 @@
LibraryIndex.tearoffPrefix + 'lookupFunction'),
getNativeFieldFunction = index.getTopLevelProcedure(
'dart:nativewrappers', '_getNativeField'),
+ finalizableClass = index.getClass('dart:ffi', 'Finalizable'),
reachabilityFenceFunction =
index.getTopLevelProcedure('dart:_internal', 'reachabilityFence'),
checkAbiSpecificIntegerMappingFunction = index.getTopLevelProcedure(
diff --git a/pkg/vm/lib/transformations/ffi/finalizable.dart b/pkg/vm/lib/transformations/ffi/finalizable.dart
new file mode 100644
index 0000000..758465b
--- /dev/null
+++ b/pkg/vm/lib/transformations/ffi/finalizable.dart
@@ -0,0 +1,894 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/type_environment.dart';
+
+/// Implements the `Finalizable` semantics.
+///
+/// Designed to be mixed in. Calls super.visitXXX() to visit all nodes (except
+/// the ones created by this transformation).
+///
+/// This transformation is not AST-node preserving. [Expression]s and
+/// [Statement]s can be replaced by other [Expression]s and [Statement]s
+/// respectively. This means one cannot do `visitX() { super.visitX() as X }`.
+mixin FinalizableTransformer on Transformer {
+ TypeEnvironment get env;
+ Procedure get reachabilityFenceFunction;
+ Class get finalizableClass;
+
+ StaticTypeContext? staticTypeContext;
+
+ _Scope? _currentScope;
+
+ bool thisIsFinalizable = false;
+
+ /// Traverses [f] in a newly created [_Scope].
+ ///
+ /// Any declarations added to this new scope will be fenced in
+ /// [appendFencesToStatement] and [appendFencesToExpression] if provided.
+ ///
+ /// Captures need to be precomputed (by [FindCaptures]) and can be passed in
+ /// through [precomputedCaptureScope].
+ ///
+ /// [declaresThis] is true if `this` in the scope is `Finalizable` and
+ /// defined.
+ T inScope<T>(
+ TreeNode node,
+ T Function() f, {
+ Statement? appendFencesToStatement,
+ Expression? appendFencesToExpression,
+ bool? declaresThis,
+ _Scope? precomputedCaptureScope,
+ }) {
+ final scope =
+ _Scope(node, parent: _currentScope, declaresThis: declaresThis);
+ if (precomputedCaptureScope != null) {
+ scope._capturesThis = precomputedCaptureScope._capturesThis;
+ scope._captures = precomputedCaptureScope._captures;
+ }
+ _currentScope = scope;
+ final result = f();
+ if (appendFencesToStatement != null) {
+ _appendReachabilityFences(
+ appendFencesToStatement, scope.toFenceThisScope);
+ }
+ if (appendFencesToExpression != null) {
+ appendFencesToExpression.replaceWith(_wrapReachabilityFences(
+ appendFencesToExpression, scope.toFenceThisScope));
+ }
+ assert(_currentScope == scope);
+ _currentScope = _currentScope!.parent;
+ return result;
+ }
+
+ Map<LocalFunction, _Scope> _precomputedCaptures = {};
+
+ _Scope? _precomputeCaptures(LocalFunction node) {
+ if (_currentScope!.allDeclarationsIsEmpty) {
+ // There's nothing we can capture.
+ return null;
+ }
+ final lookup = _precomputedCaptures[node];
+ if (lookup != null) {
+ return lookup;
+ }
+ final visitor =
+ FindCaptures(_currentScope!, thisIsFinalizable, _isFinalizable);
+ visitor.visitLocalFunction(node);
+ _precomputedCaptures = visitor.precomputedScopes;
+ return _precomputedCaptures[node]!;
+ }
+
+ @override
+ visitField(Field node) {
+ assert(staticTypeContext == null);
+ staticTypeContext = StaticTypeContext(node, env);
+ assert(_currentScope == null);
+ assert(thisIsFinalizable == false);
+ thisIsFinalizable = _thisIsFinalizableFromMember(node);
+ final result = inScope(
+ node,
+ () => super.visitField(node),
+ declaresThis: thisIsFinalizable,
+ );
+ thisIsFinalizable = false;
+ staticTypeContext = null;
+ return result;
+ }
+
+ @override
+ visitConstructor(Constructor node) {
+ assert(staticTypeContext == null);
+ staticTypeContext = StaticTypeContext(node, env);
+ assert(_currentScope == null);
+ assert(thisIsFinalizable == false);
+ thisIsFinalizable = _thisIsFinalizableFromMember(node);
+ final result = inScope(
+ node,
+ () => super.visitConstructor(node),
+ appendFencesToStatement: node.function.body,
+ declaresThis: thisIsFinalizable,
+ );
+ thisIsFinalizable = false;
+ staticTypeContext = null;
+ return result;
+ }
+
+ @override
+ visitProcedure(Procedure node) {
+ assert(staticTypeContext == null);
+ staticTypeContext = StaticTypeContext(node, env);
+ assert(_currentScope == null);
+ assert(thisIsFinalizable == false);
+ thisIsFinalizable = _thisIsFinalizableFromMember(node);
+ final result = inScope(
+ node,
+ () => super.visitProcedure(node),
+ appendFencesToStatement: node.function.body,
+ declaresThis: thisIsFinalizable,
+ );
+ thisIsFinalizable = false;
+ staticTypeContext = null;
+ return result;
+ }
+
+ @override
+ TreeNode visitBlock(Block node) {
+ return inScope(
+ node,
+ () => super.visitBlock(node),
+ appendFencesToStatement: node,
+ );
+ }
+
+ @override
+ TreeNode visitForInStatement(ForInStatement node) {
+ return inScope(
+ node,
+ () => super.visitForInStatement(node),
+ appendFencesToStatement: node.body,
+ );
+ }
+
+ @override
+ TreeNode visitForStatement(ForStatement node) {
+ return inScope(
+ node,
+ () => super.visitForStatement(node),
+ appendFencesToStatement: node.body,
+ );
+ }
+
+ @override
+ TreeNode visitLet(Let node) {
+ return inScope(
+ node,
+ () => super.visitLet(node),
+ appendFencesToExpression: node.body,
+ );
+ }
+
+ @override
+ TreeNode visitFunctionDeclaration(FunctionDeclaration node) {
+ return inScope(
+ node,
+ () => super.visitFunctionDeclaration(node),
+ appendFencesToStatement: node.function.body,
+ precomputedCaptureScope: _precomputeCaptures(node),
+ );
+ }
+
+ @override
+ TreeNode visitFunctionExpression(FunctionExpression node) {
+ return inScope(
+ node,
+ () => super.visitFunctionExpression(node),
+ appendFencesToStatement: node.function.body,
+ precomputedCaptureScope: _precomputeCaptures(node),
+ );
+ }
+
+ @override
+ TreeNode visitTryCatch(TryCatch node) {
+ return inScope(
+ node,
+ () => super.visitTryCatch(node),
+ );
+ }
+
+ @override
+ TreeNode visitCatch(Catch node) {
+ return inScope(
+ node,
+ () => super.visitCatch(node),
+ );
+ }
+
+ @override
+ TreeNode visitSwitchStatement(SwitchStatement node) {
+ return inScope(
+ node,
+ () => super.visitSwitchStatement(node),
+ );
+ }
+
+ @override
+ TreeNode visitVariableDeclaration(VariableDeclaration node) {
+ if (_currentScope == null) {
+ // Global variable.
+ return super.visitVariableDeclaration(node);
+ }
+ if (_isFinalizable(node.type)) {
+ _currentScope!.addDeclaration(node);
+ }
+ return super.visitVariableDeclaration(node);
+ }
+
+ @override
+ TreeNode visitVariableSet(VariableSet node) {
+ node = super.visitVariableSet(node) as VariableSet;
+ if (!_isFinalizable(node.variable.type)) {
+ return node;
+ }
+
+ final expression = node.value;
+
+ final newExpression = _wrapReachabilityFences(
+ expression,
+ [VariableGet(node.variable)],
+ );
+
+ node.value = newExpression;
+ newExpression.parent = node;
+
+ return node;
+ }
+
+ @override
+ TreeNode visitReturnStatement(ReturnStatement node) {
+ final declarations = _currentScope!.toFenceReturn;
+ node = super.visitReturnStatement(node) as ReturnStatement;
+ if (declarations.isEmpty) {
+ return node;
+ }
+
+ final expression = node.expression;
+ if (expression == null) {
+ final newStatement = Block([
+ ..._reachabilityFences(declarations),
+ node,
+ ]);
+ return newStatement;
+ }
+
+ final newExpression = _wrapReachabilityFences(expression, declarations);
+
+ node.expression = newExpression;
+ newExpression.parent = node;
+
+ return node;
+ }
+
+ /// The async transform runs after this transform. It transforms
+ /// [YieldStatement]s in async* functions into:
+ /// ```
+ /// _AsyncStarStreamController controller;
+ /// if(controller.add(...){
+ /// return ...
+ /// } else {
+ /// yield ...
+ /// }
+ /// ```
+ /// We don't want to run this transform after the async transform because that
+ /// introduces new scoping and control flow and it would create another
+ /// traversal over the AST.
+ /// So, we need to insert fences for yields as if they were returns in async*
+ /// functions.
+ ///
+ /// However, there is more. The body of async* and sync* functions is
+ /// transformed into a 'closure', which branches on the yield index and is
+ /// executed multiple times. The context of this closure is restored on
+ /// re-execution. These two things make it a continuation.
+ /// The [YieldStatement]s are compiled into returns from that closure.
+ /// When inlining the iterator machinery and eleminating dead code, the
+ /// compiler can see that we will never execute a re-entry if we just ask for
+ /// only the first value of a stream from a sync* function.
+ /// So, we need to insert fences for yields as if they were returns in sync*
+ /// functions as well.
+ @override
+ TreeNode visitYieldStatement(YieldStatement node) {
+ final declarations = _currentScope!.toFenceReturn;
+ node = super.visitYieldStatement(node) as YieldStatement;
+ if (declarations.isEmpty) {
+ return node;
+ }
+
+ final newExpression =
+ _wrapReachabilityFences(node.expression, declarations);
+
+ node.expression = newExpression;
+ newExpression.parent = node;
+
+ return node;
+ }
+
+ /// [AwaitExpression]s are transformed into [YieldStatement]s by the
+ /// async transform. See the comment on [visitYieldStatement].
+ @override
+ TreeNode visitAwaitExpression(AwaitExpression node) {
+ final declarations = _currentScope!.toFenceReturn;
+ node = super.visitAwaitExpression(node) as AwaitExpression;
+ if (declarations.isEmpty) {
+ return node;
+ }
+
+ final newExpression = _wrapReachabilityFences(node.operand, declarations);
+
+ node.operand = newExpression;
+ newExpression.parent = node;
+
+ return node;
+ }
+
+ @override
+ TreeNode visitThrow(Throw node) {
+ final declarations = _currentScope!.toFenceThrow(
+ staticTypeContext!.getExpressionType(node.expression), env);
+ node = super.visitThrow(node) as Throw;
+ if (declarations.isEmpty) {
+ return node;
+ }
+
+ final newExpression =
+ _wrapReachabilityFences(node.expression, declarations);
+
+ node.expression = newExpression;
+ newExpression.parent = node;
+
+ return node;
+ }
+
+ @override
+ TreeNode visitRethrow(Rethrow node) {
+ final declarations = _currentScope!.toFenceRethrow(
+ _currentScope!.rethrowType,
+ env,
+ );
+ node = super.visitRethrow(node) as Rethrow;
+ if (declarations.isEmpty) {
+ return node;
+ }
+
+ return BlockExpression(
+ Block(<Statement>[
+ ..._reachabilityFences(declarations),
+ ]),
+ node,
+ );
+ }
+
+ @override
+ TreeNode visitBreakStatement(BreakStatement node) {
+ final declarations = _currentScope!.toFenceBreak(node.target);
+
+ if (declarations.isEmpty) {
+ return node;
+ }
+
+ final newStatement = Block([
+ ..._reachabilityFences(declarations),
+ node,
+ ]);
+ return newStatement;
+ }
+
+ @override
+ TreeNode visitLabeledStatement(LabeledStatement node) {
+ _currentScope!._labels.add(node);
+ return super.visitLabeledStatement(node);
+ }
+
+ @override
+ TreeNode visitContinueSwitchStatement(ContinueSwitchStatement node) {
+ final switchStatement = node.target.parent as SwitchStatement;
+ final declarations = _currentScope!.toFenceSwitchContinue(switchStatement);
+
+ if (declarations.isEmpty) {
+ return node;
+ }
+
+ final newStatement = Block([
+ ..._reachabilityFences(declarations),
+ node,
+ ]);
+ return newStatement;
+ }
+
+ /// Cache for [isFinalizable].
+ ///
+ /// Speeds up the type checks by about a factor of 2 on Flutter Gallery.
+ Map<DartType, bool> _isFinalizableCache = {};
+
+ /// Whether [type] is something that subtypes `FutureOr<Finalizable?>?`.
+ bool _isFinalizable(DartType type) {
+ final cached = _isFinalizableCache[type];
+ if (cached != null) {
+ return cached;
+ }
+
+ final finalizableType = FutureOrType(
+ InterfaceType(finalizableClass, Nullability.nullable),
+ Nullability.nullable);
+ if (!env.isSubtypeOf(
+ type,
+ finalizableType,
+ SubtypeCheckMode.withNullabilities,
+ )) {
+ _isFinalizableCache[type] = false;
+ return false;
+ }
+
+ // Exclude never types.
+ final futureOfNeverType =
+ FutureOrType(NeverType.nullable(), Nullability.nullable);
+ final result = !env.isSubtypeOf(
+ type,
+ futureOfNeverType,
+ SubtypeCheckMode.ignoringNullabilities,
+ );
+ _isFinalizableCache[type] = result;
+ return result;
+ }
+
+ bool _thisIsFinalizableFromMember(Member member) {
+ final enclosingClass_ = member.enclosingClass;
+ if (enclosingClass_ == null) {
+ return false;
+ }
+ if (member.isAbstract) {
+ return false;
+ }
+ if (member.isExternal) {
+ return false;
+ }
+ if (member is Constructor && member.isSynthetic) {
+ return false;
+ }
+ if (member is Procedure && member.isStatic) {
+ return false;
+ }
+ return _isFinalizable(
+ InterfaceType(enclosingClass_, Nullability.nonNullable));
+ }
+
+ List<Statement> _reachabilityFences(List<Expression> declarations) =>
+ <Statement>[
+ for (var declaration in declarations)
+ ExpressionStatement(
+ StaticInvocation(
+ reachabilityFenceFunction,
+ Arguments(<Expression>[declaration]),
+ ),
+ ),
+ ];
+
+ /// Turns an [expression] into a block expression with reachability fences.
+ ///
+ /// ```
+ /// block {
+ /// final <expression type> #t1 = <expression>;
+ /// _in::reachabilityFence(finalizable0);
+ /// _in::reachabilityFence(finalizable1);
+ /// // ..
+ /// } =>#t1
+ /// ```
+ ///
+ /// Note that this modifies the parent of [expression].
+ Expression _wrapReachabilityFences(
+ Expression expression, List<Expression> declarations) {
+ final resultVariable = VariableDeclaration(
+ ':expressionValueWrappedFinalizable',
+ initializer: expression,
+ type: staticTypeContext!.getExpressionType(expression),
+ isFinal: true);
+ return BlockExpression(
+ Block(<Statement>[
+ resultVariable,
+ ..._reachabilityFences(declarations),
+ ]),
+ VariableGet(resultVariable),
+ );
+ }
+
+ Statement _appendReachabilityFences(
+ Statement statement, List<Expression> declarations) {
+ if (declarations.isEmpty) {
+ return statement;
+ }
+ Block block = () {
+ if (statement is Block) {
+ return statement;
+ }
+ final replacement = Block(<Statement>[]);
+ statement.replaceWith(replacement);
+ replacement.statements.add(statement);
+ return replacement;
+ }();
+ if (block.statements.isEmpty ||
+ (!block.statements.last.endsWithAbnormalControlFlow)) {
+ block.statements.addAll(_reachabilityFences(declarations));
+ }
+ return block;
+ }
+}
+
+/// A lightweight version of the above transform that precomputes scopes.
+///
+/// We need to precompute scopes and captures because a variable can be captured
+/// later in a closure than the first return.
+///
+/// We cannot use the precomputed scopes for their declarations, because we
+/// could see returns in a scope before a declaration.
+class FindCaptures extends RecursiveVisitor<void> {
+ final bool Function(DartType) _isFinalizable;
+
+ final bool thisIsFinalizable;
+
+ final Map<LocalFunction, _Scope> precomputedScopes = {};
+
+ _Scope _currentScope;
+
+ FindCaptures(this._currentScope, this.thisIsFinalizable, this._isFinalizable);
+
+ void inScope(LocalFunction node, void Function() f) {
+ final scope = _Scope(node, parent: _currentScope, declaresThis: false);
+ assert(precomputedScopes[node] == null);
+ precomputedScopes[node] = scope;
+ _currentScope = scope;
+ final result = f();
+ assert(_currentScope == scope);
+ _currentScope = _currentScope.parent!;
+ return result;
+ }
+
+ void visitLocalFunction(LocalFunction node) {
+ if (node is FunctionDeclaration) {
+ return visitFunctionDeclaration(node);
+ }
+ if (node is FunctionExpression) {
+ return visitFunctionExpression(node);
+ }
+ assert(false);
+ }
+
+ @override
+ void visitFunctionDeclaration(FunctionDeclaration node) {
+ inScope(
+ node,
+ () => super.visitFunctionDeclaration(node),
+ );
+ }
+
+ @override
+ void visitFunctionExpression(FunctionExpression node) {
+ inScope(
+ node,
+ () => super.visitFunctionExpression(node),
+ );
+ }
+
+ @override
+ void visitVariableDeclaration(VariableDeclaration node) {
+ if (_isFinalizable(node.type)) {
+ _currentScope.addDeclaration(node);
+ }
+ super.visitVariableDeclaration(node);
+ }
+
+ @override
+ void visitVariableGet(VariableGet node) {
+ super.visitVariableGet(node);
+ if (_isFinalizable(node.variable.type)) {
+ _currentScope.addCapture(node.variable);
+ }
+ }
+
+ @override
+ void visitVariableSet(VariableSet node) {
+ super.visitVariableSet(node);
+ if (_isFinalizable(node.variable.type)) {
+ _currentScope.addCapture(node.variable);
+ }
+ }
+
+ @override
+ void visitThisExpression(ThisExpression node) {
+ if (thisIsFinalizable) {
+ _currentScope.addCaptureThis();
+ }
+ super.visitThisExpression(node);
+ }
+}
+
+/// A scope contains all `Finalizable` declarations and captures.
+class _Scope {
+ /// Parent scope if any.
+ final _Scope? parent;
+
+ /// The [node] introducing this scope.
+ final TreeNode node;
+
+ /// The declarations in this scope.
+ ///
+ /// The list is mutable, because we populate it during visiting statements.
+ ///
+ /// We use a list rather than a set because declarations are unique and we'd
+ /// like to prevent arbitrary reorderings when generating code from this.
+ final List<VariableDeclaration> _declarations = [];
+
+ /// [ThisExpression] is not a [VariableDeclaration] and needs to be tracked
+ /// separately.
+ final bool declaresThis;
+
+ /// Labels defined in this scope.
+ ///
+ /// Used for seeing which declarations need to be fenced when encountering
+ /// a [BreakStatement];
+ final Set<LabeledStatement> _labels = {};
+
+ _Scope(this.node, {this.parent, bool? declaresThis})
+ : this.declaresThis = declaresThis ?? false,
+ this.allDeclarationsIsEmpty =
+ (parent?.allDeclarationsIsEmpty ?? true) &&
+ !(declaresThis ?? false);
+
+ void addDeclaration(VariableDeclaration declaration) {
+ _declarations.add(declaration);
+ allDeclarationsIsEmpty = false;
+ }
+
+ /// Whether [allDeclarations] is empty.
+ ///
+ /// Manually cached for performance.
+ bool allDeclarationsIsEmpty;
+
+ /// All declarations in this and parent scopes.
+ ///
+ /// Excluding `this`.
+ List<VariableDeclaration> get allDeclarations => [
+ ...?parent?.allDeclarations,
+ ..._declarations,
+ ];
+
+ bool get canCapture => node is LocalFunction;
+
+ /// Which of the ancestor scopes (or this) captures variables.
+ late final _Scope? capturingScope = () {
+ if (canCapture) {
+ return this;
+ }
+ return parent?.capturingScope;
+ }();
+
+ Map<VariableDeclaration, bool>? _captures;
+
+ Map<VariableDeclaration, bool> get captures {
+ if (_captures != null) {
+ return _captures!;
+ }
+
+ assert(canCapture);
+ _captures = {for (var d in parent!.allDeclarations) d: false};
+ return _captures!;
+ }
+
+ bool _capturesThis = false;
+
+ void addCapture(VariableDeclaration declaration) {
+ final capturingScope_ = capturingScope;
+ if (capturingScope_ == null) {
+ // We're not in a nested closure.
+ return;
+ }
+
+ final captures = capturingScope_.captures;
+ if (!captures.containsKey(declaration)) {
+ // This is a local variable, not a captured one.
+ return;
+ }
+ captures[declaration] = true;
+
+ capturingScope_.parent?.addCapture(declaration);
+ }
+
+ void addCaptureThis() {
+ final capturingScope_ = capturingScope;
+ if (capturingScope_ == null) {
+ // We're not in a nested closure.
+ return;
+ }
+
+ capturingScope_._capturesThis = true;
+
+ capturingScope_.parent?.addCaptureThis();
+ }
+
+ /// Get declarations in this scope.
+ List<Expression> get toFenceThisScope {
+ final captures = _captures;
+ return [
+ if (declaresThis || _capturesThis) ThisExpression(),
+ for (var d in _declarations) VariableGet(d),
+ if (captures != null)
+ for (var d in captures.entries.where((e) => e.value).map((e) => e.key))
+ VariableGet(d),
+ ];
+ }
+
+ /// Whether when a return is found, this is the last ancestor of which
+ /// declarations should be considered.
+ bool get scopesReturn {
+ assert(node is Block ||
+ node is Catch ||
+ node is ForInStatement ||
+ node is ForStatement ||
+ node is Let ||
+ node is LocalFunction ||
+ node is Member ||
+ node is SwitchStatement ||
+ node is TryCatch);
+ return node is Member || node is LocalFunction;
+ }
+
+ /// Get all declarations that should stay alive on a return.
+ ///
+ /// This include all declarations in scopes until we see a function scope.
+ List<Expression> get toFenceReturn {
+ return [
+ if (!scopesReturn) ...parent!.toFenceReturn,
+ ...toFenceThisScope,
+ ];
+ }
+
+ List<Expression> toFenceBreak(LabeledStatement label) {
+ if (_labels.contains(label)) {
+ return [];
+ }
+ return [
+ ...parent!.toFenceBreak(label),
+ ...toFenceThisScope,
+ ];
+ }
+
+ List<Expression> toFenceSwitchContinue(SwitchStatement switchStatement) {
+ if (node == switchStatement) {
+ return [];
+ }
+ return [
+ ...parent!.toFenceSwitchContinue(switchStatement),
+ ...toFenceThisScope,
+ ];
+ }
+
+ bool scopesThrow(DartType exceptionType, TypeEnvironment typeEnvironment) {
+ final node_ = node;
+ if (node_ is! TryCatch) {
+ return false;
+ }
+ final catches = node_.catches;
+ for (final catch_ in catches) {
+ if (typeEnvironment.isSubtypeOf(
+ exceptionType, catch_.guard, SubtypeCheckMode.withNullabilities)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ List<Expression> toFenceThrow(
+ DartType exceptionType,
+ TypeEnvironment typeEnvironment,
+ ) =>
+ [
+ if (!scopesThrow(exceptionType, typeEnvironment))
+ ...?parent?.toFenceThrow(exceptionType, typeEnvironment),
+ ...toFenceThisScope,
+ ];
+
+ DartType get rethrowType {
+ final node_ = node;
+ if (node_ is Catch) {
+ return node_.guard;
+ }
+ return parent!.rethrowType;
+ }
+
+ List<Expression> toFenceRethrow(
+ DartType exceptionType, TypeEnvironment typeEnvironment) {
+ return [
+ if (!scopesThrow(exceptionType, typeEnvironment))
+ ...?parent?.toFenceRethrow(exceptionType, typeEnvironment),
+ if (scopesThrow(exceptionType, typeEnvironment))
+ ...?parent?.toFenceThrow(exceptionType, typeEnvironment),
+ ...toFenceThisScope,
+ ];
+ }
+}
+
+extension on Statement {
+ /// Whether this statement ends with abnormal control flow.
+ ///
+ /// Used to avoid inserting definitely dead reachabilityFences.
+ ///
+ /// Recurses into [Block]s to inspect their last statement.
+ ///
+ /// Examples:
+ ///
+ /// ```dart
+ /// {
+ /// // ...
+ /// return 5;
+ /// }
+ /// ```
+ ///
+ /// returns true.
+ ///
+ /// ```dart
+ /// {
+ /// {
+ /// break L2;
+ /// }
+ /// }
+ /// ```
+ ///
+ /// returns true.
+ ///
+ /// ```dart
+ /// print(foo);
+ /// ```
+ ///
+ /// returns false.
+ ///
+ /// Does not take into consideration full control flow, rather this is best
+ /// effort:
+ ///
+ /// ```dart
+ /// {
+ /// return 42;
+ /// var unreachable = true;
+ /// }
+ /// ```
+ ///
+ /// returns false, even though inserting fences is superfluous.
+ ///
+ /// These extra fences are not unsound.
+ bool get endsWithAbnormalControlFlow {
+ if (this is ReturnStatement) {
+ return true;
+ }
+ if (this is BreakStatement) {
+ return true;
+ }
+ if (this is ContinueSwitchStatement) {
+ return true;
+ }
+ if (this is Throw) {
+ return true;
+ }
+ if (this is Rethrow) {
+ return true;
+ }
+ final this_ = this;
+ if (this_ is Block) {
+ final statements = this_.statements;
+ if (statements.isEmpty) {
+ return false;
+ }
+ return statements.last.endsWithAbnormalControlFlow;
+ }
+ return false;
+ }
+}
diff --git a/pkg/vm/lib/transformations/ffi/use_sites.dart b/pkg/vm/lib/transformations/ffi/use_sites.dart
index ba1a0b1..0a765e3 100644
--- a/pkg/vm/lib/transformations/ffi/use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi/use_sites.dart
@@ -20,6 +20,7 @@
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart';
+import 'package:kernel/kernel.dart';
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/reference_from_index.dart';
import 'package:kernel/target/targets.dart' show DiagnosticReporter;
@@ -30,6 +31,7 @@
import 'native_type_cfe.dart';
import 'common.dart'
show NativeType, FfiTransformer, nativeTypeSizes, WORD_SIZE, UNKNOWN;
+import 'finalizable.dart';
/// Checks and replaces calls to dart:ffi compound fields and methods.
void transformLibraries(
@@ -51,22 +53,20 @@
// If dart:ffi is not loaded (for real): do not do the transformation.
return;
}
- final transformer = new _FfiUseSiteTransformer(
+ final transformer = new _FfiUseSiteTransformer2(
index, coreTypes, hierarchy, diagnosticReporter, referenceFromIndex);
libraries.forEach(transformer.visitLibrary);
}
-/// Checks and replaces calls to dart:ffi compound fields and methods.
-class _FfiUseSiteTransformer extends FfiTransformer {
- StaticTypeContext? _staticTypeContext;
-
- bool get isFfiLibrary => currentLibrary == ffiLibrary;
-
- // Used to create private top-level fields with unique names for each
- // callback.
- int callbackCount = 0;
-
- _FfiUseSiteTransformer(
+/// Combines [_FfiUseSiteTransformer] and [FinalizableTransformer] into a single
+/// traversal.
+///
+/// This transformation is not AST-node preserving. [Expression]s and
+/// [Statement]s can be replaced by other [Expression]s and [Statement]s
+/// respectively. This means one cannot do `visitX() { super.visitX() as X }`.
+class _FfiUseSiteTransformer2 extends FfiTransformer
+ with _FfiUseSiteTransformer, FinalizableTransformer {
+ _FfiUseSiteTransformer2(
LibraryIndex index,
CoreTypes coreTypes,
ClassHierarchy hierarchy,
@@ -74,6 +74,26 @@
ReferenceFromIndex? referenceFromIndex)
: super(index, coreTypes, hierarchy, diagnosticReporter,
referenceFromIndex);
+}
+
+/// Checks and replaces calls to dart:ffi compound fields and methods.
+///
+/// Designed to be mixed in. Calls super.visitXXX() to visit all nodes (except
+/// the ones created by this transformation).
+///
+/// This transformation is not AST-node preserving. [Expression]s and
+/// [Statement]s can be replaced by other [Expression]s and [Statement]s
+/// respectively. This means one cannot do `visitX() { super.visitX() as X }`.
+mixin _FfiUseSiteTransformer on FfiTransformer {
+ StaticTypeContext? get staticTypeContext;
+
+ bool _inFfiTearoff = false;
+
+ bool get isFfiLibrary => currentLibrary == ffiLibrary;
+
+ // Used to create private top-level fields with unique names for each
+ // callback.
+ int callbackCount = 0;
@override
TreeNode visitLibrary(Library node) {
@@ -95,42 +115,34 @@
}
@override
- visitField(Field node) {
- _staticTypeContext = new StaticTypeContext(node, env);
- var result = super.visitField(node);
- _staticTypeContext = null;
- return result;
- }
-
- @override
- visitConstructor(Constructor node) {
- _staticTypeContext = new StaticTypeContext(node, env);
- var result = super.visitConstructor(node);
- _staticTypeContext = null;
- return result;
- }
-
- @override
visitProcedure(Procedure node) {
- if (isFfiLibrary && node.isExtensionMember) {
- if (node == allocationTearoff ||
- node == asFunctionTearoff ||
- node == lookupFunctionTearoff) {
- // Skip static checks and transformation for the tearoffs.
- return node;
- }
- }
-
- _staticTypeContext = new StaticTypeContext(node, env);
+ assert(_inFfiTearoff == false);
+ _inFfiTearoff = (isFfiLibrary &&
+ node.isExtensionMember &&
+ (node == allocationTearoff ||
+ node == asFunctionTearoff ||
+ node == lookupFunctionTearoff));
final result = super.visitProcedure(node);
- _staticTypeContext = null;
+ _inFfiTearoff = false;
return result;
}
@override
- visitStaticInvocation(StaticInvocation node) {
- super.visitStaticInvocation(node);
+ TreeNode visitStaticInvocation(StaticInvocation node) {
+ final modifiedExpression = _visitStaticInvocation(node);
+ if (node == modifiedExpression) {
+ return super.visitStaticInvocation(node);
+ }
+ // We've just created this node. We're likely not going to need to transform
+ // this node itself. Visit its sub exprssions.
+ return super.defaultExpression(modifiedExpression);
+ }
+ /// Replaces nodes if they match. Does not invoke any super visit.
+ Expression _visitStaticInvocation(StaticInvocation node) {
+ if (_inFfiTearoff) {
+ return node;
+ }
final Member target = node.target;
try {
if (target == abiSpecificIntegerPointerGetValue ||
@@ -141,7 +153,7 @@
target == abiSpecificIntegerArraySetElemAt) {
final pointer = node.arguments.positional[0];
final pointerType =
- pointer.getStaticType(_staticTypeContext!) as InterfaceType;
+ pointer.getStaticType(staticTypeContext!) as InterfaceType;
_ensureNativeTypeValid(pointerType, pointer,
allowCompounds: true, allowInlineArray: true);
@@ -279,7 +291,7 @@
final DartType nativeType = InterfaceType(
nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
final Expression func = node.arguments.positional[0];
- final DartType dartType = func.getStaticType(_staticTypeContext!);
+ final DartType dartType = func.getStaticType(staticTypeContext!);
_ensureIsStaticFunction(func);
@@ -345,7 +357,7 @@
}
final DartType returnType =
- exceptionalReturn.getStaticType(_staticTypeContext!);
+ exceptionalReturn.getStaticType(staticTypeContext!);
if (!env.isSubtypeOf(returnType, funcType.returnType,
SubtypeCheckMode.ignoringNullabilities)) {
@@ -746,13 +758,25 @@
@override
visitInstanceInvocation(InstanceInvocation node) {
- super.visitInstanceInvocation(node);
+ final modifiedExpression = _visitInstanceInvocation(node);
+ if (node == modifiedExpression) {
+ return super.visitInstanceInvocation(node);
+ }
+ // We've just created this node. We're likely not going to need to transform
+ // this node itself. Visit its sub exprssions.
+ return super.defaultExpression(modifiedExpression);
+ }
+ /// Replaces nodes if they match. Does not invoke any super visit.
+ Expression _visitInstanceInvocation(InstanceInvocation node) {
+ if (_inFfiTearoff) {
+ return node;
+ }
final Member target = node.interfaceTarget;
try {
if (target == elementAtMethod) {
final DartType pointerType =
- node.receiver.getStaticType(_staticTypeContext!);
+ node.receiver.getStaticType(staticTypeContext!);
final DartType nativeType = _pointerTypeGetTypeArg(pointerType)!;
_ensureNativeTypeValid(nativeType, node, allowCompounds: true);
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 66cf72d..d44ca15 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -65,7 +65,8 @@
});
test('compile', () async {
- IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
+ IncrementalCompiler compiler =
+ new IncrementalCompiler(options, [main.uri]);
IncrementalCompilerResult compilerResult = await compiler.compile();
Component component = compilerResult.component;
@@ -84,7 +85,7 @@
CompilerOptions optionsExcludeSources = getFreshOptions()
..embedSourceText = false;
IncrementalCompiler compiler =
- new IncrementalCompiler(optionsExcludeSources, main.uri);
+ new IncrementalCompiler(optionsExcludeSources, [main.uri]);
IncrementalCompilerResult compilerResult = await compiler.compile();
Component component = compilerResult.component;
@@ -111,7 +112,7 @@
message.plainTextFormatted.forEach(print);
};
IncrementalCompiler compiler =
- new IncrementalCompiler(optionsAcceptErrors, main.uri);
+ new IncrementalCompiler(optionsAcceptErrors, [main.uri]);
await compiler.compile();
compiler.accept();
{
@@ -362,7 +363,8 @@
Directory dir = mytest.createTempSync();
File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
File libDill = File(p.join(dir.path, p.basename(lib.path + ".dill")));
- IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
+ IncrementalCompiler compiler =
+ new IncrementalCompiler(options, [main.uri]);
await compileAndSerialize(mainDill, libDill, compiler);
var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
@@ -389,7 +391,8 @@
Directory dir = mytest.createTempSync();
File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
File libDill = File(p.join(dir.path, p.basename(lib.path + ".dill")));
- IncrementalCompiler compiler = new IncrementalCompiler(options, lib.uri);
+ IncrementalCompiler compiler =
+ new IncrementalCompiler(options, [lib.uri]);
await compileAndSerialize(mainDill, libDill, compiler);
var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
@@ -453,7 +456,8 @@
Directory dir = mytest.createTempSync();
File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
File libDill = File(p.join(dir.path, p.basename(lib.path + ".dill")));
- IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
+ IncrementalCompiler compiler =
+ new IncrementalCompiler(options, [main.uri]);
await compileAndSerialize(mainDill, libDill, compiler);
var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
@@ -481,7 +485,8 @@
Directory dir = mytest.createTempSync();
File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
File libDill = File(p.join(dir.path, p.basename(lib.path + ".dill")));
- IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
+ IncrementalCompiler compiler =
+ new IncrementalCompiler(options, [main.uri]);
await compileAndSerialize(mainDill, libDill, compiler);
var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
@@ -642,7 +647,8 @@
// Note that it's called 'lib1' to match with expectations from coverage
// collector helper in this file.
File libDill = File(p.join(dir.path, p.basename(lib1.path + ".dill")));
- IncrementalCompiler compiler = new IncrementalCompiler(options, lib1.uri);
+ IncrementalCompiler compiler =
+ new IncrementalCompiler(options, [lib1.uri]);
IncrementalCompilerResult compilerResult = await compiler.compile();
Component component = compilerResult.component;
expect(component.libraries.length, equals(1));
@@ -672,7 +678,7 @@
// Then compile lib, run and verify coverage (un-named constructor
// covered, and the named constructor coveraged too).
File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
- compilerResult = await compiler.compile(entryPoint: main.uri);
+ compilerResult = await compiler.compile(entryPoints: [main.uri]);
component = compilerResult.component;
expect(component.libraries.length, equals(1));
expect(component.libraries.single.fileUri, equals(main.uri));
@@ -730,7 +736,7 @@
int newLineForUnnamedConstructor = 8;
int newLineForNamedConstructor = 9;
compiler.invalidate(lib1.uri);
- compilerResult = await compiler.compile(entryPoint: lib1.uri);
+ compilerResult = await compiler.compile(entryPoints: [lib1.uri]);
component = compilerResult.component;
expect(component.libraries.length, equals(1));
expect(component.libraries.single.fileUri, equals(lib1.uri));
@@ -848,7 +854,8 @@
File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
File lib1Dill = File(p.join(dir.path, p.basename(lib1.path + ".dill")));
File lib2Dill = File(p.join(dir.path, p.basename(lib2.path + ".dill")));
- IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
+ IncrementalCompiler compiler =
+ new IncrementalCompiler(options, [main.uri]);
await compileAndSerialize(mainDill, lib1Dill, lib2Dill, compiler);
var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
@@ -926,7 +933,8 @@
fileBaz.writeAsStringSync("import 'dart:isolate';\n"
"openReceivePortSoWeWontDie() { new RawReceivePort(); }\n");
- IncrementalCompiler compiler = new IncrementalCompiler(options, file.uri);
+ IncrementalCompiler compiler =
+ new IncrementalCompiler(options, [file.uri]);
IncrementalCompilerResult compilerResult = await compiler.compile();
Component component = compilerResult.component;
@@ -1046,10 +1054,10 @@
CompilerOptions optionsModified = getFreshOptions()
..packagesFileUri = packageUri;
IncrementalCompiler compiler =
- new IncrementalCompiler(optionsModified, packageEntry);
+ new IncrementalCompiler(optionsModified, [packageEntry]);
{
IncrementalCompilerResult compilerResult =
- await compiler.compile(entryPoint: packageEntry);
+ await compiler.compile(entryPoints: [packageEntry]);
Component component = compilerResult.component;
File outputFile = new File('${mytest.path}/foo.dart.dill');
await _writeProgramToFile(component, outputFile);
@@ -1075,7 +1083,7 @@
compiler.invalidate(barUri);
{
IncrementalCompilerResult compilerResult =
- await compiler.compile(entryPoint: packageEntry);
+ await compiler.compile(entryPoints: [packageEntry]);
Component component = compilerResult.component;
File outputFile = new File('${mytest.path}/foo1.dart.dill');
await _writeProgramToFile(component, outputFile);
@@ -1124,12 +1132,12 @@
ExperimentalFlag.alternativeInvalidationStrategy] = true;
final IncrementalCompiler compiler =
- new IncrementalCompiler(optionsModified, fooUri);
+ new IncrementalCompiler(optionsModified, [fooUri]);
Library fooLib;
Library barLib;
{
final IncrementalCompilerResult compilerResult =
- await compiler.compile(entryPoint: fooUri);
+ await compiler.compile(entryPoints: [fooUri]);
final Component component = compilerResult.component;
expect(component.libraries.length, equals(2));
fooLib = component.libraries.firstWhere((lib) => lib.fileUri == fooUri);
@@ -1168,7 +1176,7 @@
compiler.invalidate(barUri);
{
final IncrementalCompilerResult compilerResult =
- await compiler.compile(entryPoint: fooUri);
+ await compiler.compile(entryPoints: [fooUri]);
final Component component = compilerResult.component;
final Library? fooLib2 = component.libraries
.firstWhereOrNull((lib) => lib.fileUri == fooUri);
@@ -1345,7 +1353,7 @@
int extra() { return 22; }
""");
IncrementalCompiler compiler =
- new IncrementalCompiler(options, mainFile.uri);
+ new IncrementalCompiler(options, [mainFile.uri]);
IncrementalCompilerResult compilerResult = await compiler.compile();
Component component = compilerResult.component;
File mainDill = new File.fromUri(mainFile.uri.resolve("main.dill"));
@@ -1419,7 +1427,7 @@
}
""");
IncrementalCompiler compiler =
- new IncrementalCompiler(options, mainFile.uri);
+ new IncrementalCompiler(options, [mainFile.uri]);
IncrementalCompilerResult compilerResult = await compiler.compile();
Component component = compilerResult.component;
File mainDill = new File.fromUri(mainFile.uri.resolve("main.dill"));
@@ -1595,7 +1603,7 @@
CompilerOptions optionsModified = getFreshOptions()
..packagesFileUri = packagesFile.uri;
IncrementalCompiler compiler =
- new IncrementalCompiler(optionsModified, mainUri);
+ new IncrementalCompiler(optionsModified, [mainUri]);
IncrementalCompilerResult compilerResult = await compiler.compile();
Component component = compilerResult.component;
diff --git a/pkg/vm/test/kernel_front_end_test.dart b/pkg/vm/test/kernel_front_end_test.dart
index effa84d..037a610c 100644
--- a/pkg/vm/test/kernel_front_end_test.dart
+++ b/pkg/vm/test/kernel_front_end_test.dart
@@ -6,6 +6,8 @@
import 'package:front_end/src/api_unstable/vm.dart'
show computePlatformBinariesLocation;
+import 'package:kernel/ast.dart' show Component;
+import 'package:kernel/kernel.dart' show loadComponentFromBinary;
import 'package:test/test.dart';
import 'package:vm/kernel_front_end.dart';
@@ -26,6 +28,15 @@
expect(compilerExitCode, successExitCode);
}
+bool containsLibrary(Component component, String name) {
+ for (final lib in component.libraries) {
+ if (lib.importUri.pathSegments.last == name) {
+ return true;
+ }
+ }
+ return false;
+}
+
main() {
late Directory tempDir;
setUp(() {
@@ -128,4 +139,28 @@
'test-filesystem-scheme:///$mainScript',
]);
}, timeout: Timeout.none);
+
+ test('multiple-sources', () async {
+ final src1 = File('${tempDir.path}/src1.dart');
+ final src2 = File('${tempDir.path}/src2.dart');
+ src1.writeAsStringSync("main() {}");
+ src2.writeAsStringSync("entryPoint() {}");
+ await testCompile([
+ '--platform',
+ platformPath(),
+ '--no-link-platform',
+ // Need to specify --packages as front-end refuses to infer
+ // its location when compiling multiple sources.
+ '--packages',
+ '$sdkDir/$packageConfigFile',
+ '--source',
+ src2.path,
+ '--output',
+ outputDill(),
+ src1.path,
+ ]);
+ final component = loadComponentFromBinary(outputDill());
+ expect(containsLibrary(component, 'src1.dart'), equals(true));
+ expect(containsLibrary(component, 'src2.dart'), equals(true));
+ }, timeout: Timeout.none);
}
diff --git a/pkg/vm/test/transformations/ffi_test.dart b/pkg/vm/test/transformations/ffi_test.dart
index cda6097..8d4f639 100644
--- a/pkg/vm/test/transformations/ffi_test.dart
+++ b/pkg/vm/test/transformations/ffi_test.dart
@@ -48,14 +48,21 @@
compareResultWithExpectationsFile(source, actual);
}
-main() {
+void main(List<String> args) {
+ assert(args.length == 0 || args.length == 1);
+ String? filter;
+ if (args.length > 0) {
+ filter = args.first;
+ }
+
group('ffi-transformations', () {
final testCasesDir = Directory(pkgVmDir + '/testcases/transformations/ffi');
for (var entry in testCasesDir
.listSync(recursive: true, followLinks: false)
.reversed) {
- if (entry.path.endsWith(".dart")) {
+ if (entry.path.endsWith(".dart") &&
+ (filter == null || entry.path.contains(filter))) {
test(entry.path, () => runTestCase(entry.uri));
}
}
diff --git a/pkg/vm/testcases/transformations/analysis_options.yaml b/pkg/vm/testcases/transformations/analysis_options.yaml
new file mode 100644
index 0000000..2db5dae
--- /dev/null
+++ b/pkg/vm/testcases/transformations/analysis_options.yaml
@@ -0,0 +1,10 @@
+# Copyright (c) 2017, 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.
+
+analyzer:
+ exclude:
+ - deferred_loading/**
+ - to_string_transformer/**
+ - type_flow/**
+ - unreachable_code_elimination/**
diff --git a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
index 328e71f..e063504 100644
--- a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
+++ b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
@@ -48,7 +48,7 @@
static method j() → dynamic /* originally async */ {
final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
dart.core::int :await_jump_var = 0;
@@ -59,7 +59,7 @@
{
dart.core::print("J");
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
@@ -79,7 +79,7 @@
static method h() → dynamic /* originally async */ {
final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
dart.core::int :await_jump_var = 0;
@@ -90,7 +90,7 @@
{
dart.core::print("H");
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
@@ -147,7 +147,7 @@
static method g() → dynamic /* originally async */ {
final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
dart.core::int :await_jump_var = 0;
@@ -158,7 +158,7 @@
{
dart.core::print("G");
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
@@ -395,7 +395,7 @@
static method main() → dynamic /* originally async */ {
final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
dart.core::int :await_jump_var = 0;
@@ -410,7 +410,7 @@
[yield] let dynamic #t14 = dart.async::_awaitHelper(b::b(), :async_op_then, :async_op_error, :async_op) in null;
:result;
}
- dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
diff --git a/pkg/vm/testcases/transformations/ffi/compound_copies.dart b/pkg/vm/testcases/transformations/ffi/compound_copies.dart
index 4717b9b..534f880 100644
--- a/pkg/vm/testcases/transformations/ffi/compound_copies.dart
+++ b/pkg/vm/testcases/transformations/ffi/compound_copies.dart
@@ -1,7 +1,5 @@
import 'dart:ffi';
-import 'package:ffi/ffi.dart';
-
class Coordinate extends Struct {
@Int64()
external int x;
diff --git a/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect b/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect
index b1fe1cf..e7341fe 100644
--- a/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect
+++ b/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect
@@ -6,7 +6,6 @@
import "dart:_internal" as _in;
import "dart:ffi";
-import "package:ffi/ffi.dart";
@#C6
class Coordinate extends ffi::Struct {
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_async.dart b/pkg/vm/testcases/transformations/ffi/finalizable_async.dart
new file mode 100644
index 0000000..d2448ed
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_async.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.16
+
+// ignore_for_file: unused_local_variable
+
+import 'dart:ffi';
+
+Future<int> doSomething() async => 3;
+
+class MyFinalizable implements Finalizable {
+ Future<int> use() async {
+ return doSomething();
+ }
+
+ Future<int> use2() async {
+ return await doSomething();
+ }
+
+ Future<int> use3() {
+ return doSomething();
+ }
+}
+
+Future<int> useFinalizableAsync(Finalizable finalizable) async {
+ await Future.sync(() => 6);
+ final finalizable2 = MyFinalizable();
+ await Future.sync(() => 5);
+ final finalizable3 = MyFinalizable();
+ await Future.sync(() => 4);
+ return doSomething();
+}
+
+void main() async {
+ final finalizable = MyFinalizable();
+ final asyncResult = useFinalizableAsync(finalizable);
+ print(await asyncResult);
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_async.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_async.dart.expect
new file mode 100644
index 0000000..f72ce42
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_async.dart.expect
@@ -0,0 +1,199 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+ synthetic constructor •() → self::MyFinalizable
+ : super core::Object::•()
+ ;
+ method use() → asy::Future<core::int> /* originally async */ {
+ final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+ core::bool* :is_sync = false;
+ FutureOr<core::int>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ :return_value = block {
+ final asy::Future<core::int> :expressionValueWrappedFinalizable = self::doSomething();
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ break #L1;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+ }
+ method use2() → asy::Future<core::int> /* originally async */ {
+ final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+ core::bool* :is_sync = false;
+ core::int? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ [yield] let dynamic #t1 = asy::_awaitHelper( block {
+ final asy::Future<core::int> :expressionValueWrappedFinalizable = self::doSomething();
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+ final core::int :expressionValueWrappedFinalizable = _in::unsafeCast<core::int>(:result);
+ :return_value = block {
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ break #L2;
+ }
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+ }
+ method use3() → asy::Future<core::int> {
+ return block {
+ final asy::Future<core::int> :expressionValueWrappedFinalizable = self::doSomething();
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ }
+}
+static method doSomething() → asy::Future<core::int> /* originally async */ {
+ final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+ core::bool* :is_sync = false;
+ core::int? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L3:
+ {
+ :return_value = 3;
+ break #L3;
+ }
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method useFinalizableAsync(ffi::Finalizable finalizable) → asy::Future<core::int> /* originally async */ {
+ final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+ core::bool* :is_sync = false;
+ FutureOr<core::int>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L4:
+ {
+ [yield] let dynamic #t2 = asy::_awaitHelper( block {
+ final asy::Future<core::int> :expressionValueWrappedFinalizable = asy::Future::sync<core::int>(() → core::int => 6);
+ _in::reachabilityFence(finalizable);
+ } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::int>(:result);
+ final self::MyFinalizable finalizable2 = new self::MyFinalizable::•();
+ [yield] let dynamic #t3 = asy::_awaitHelper( block {
+ final asy::Future<core::int> :expressionValueWrappedFinalizable = asy::Future::sync<core::int>(() → core::int => 5);
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable2);
+ } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::int>(:result);
+ final self::MyFinalizable finalizable3 = new self::MyFinalizable::•();
+ [yield] let dynamic #t4 = asy::_awaitHelper( block {
+ final asy::Future<core::int> :expressionValueWrappedFinalizable = asy::Future::sync<core::int>(() → core::int => 4);
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable2);
+ _in::reachabilityFence(finalizable3);
+ } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::int>(:result);
+ :return_value = block {
+ final asy::Future<core::int> :expressionValueWrappedFinalizable = self::doSomething();
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable2);
+ _in::reachabilityFence(finalizable3);
+ } =>:expressionValueWrappedFinalizable;
+ break #L4;
+ }
+ asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
+static method main() → void /* originally async */ {
+ final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
+ core::bool* :is_sync = false;
+ dynamic :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L5:
+ {
+ final self::MyFinalizable finalizable = new self::MyFinalizable::•();
+ final asy::Future<core::int> asyncResult = self::useFinalizableAsync(finalizable);
+ [yield] let dynamic #t5 = asy::_awaitHelper( block {
+ final asy::Future<core::int> :expressionValueWrappedFinalizable = asyncResult;
+ _in::reachabilityFence(finalizable);
+ } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+ core::print(_in::unsafeCast<core::int>(:result));
+ _in::reachabilityFence(finalizable);
+ }
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart b/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart
new file mode 100644
index 0000000..6e73ab3
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.16
+
+// ignore_for_file: unused_local_variable
+
+import 'dart:ffi';
+
+class MyFinalizable implements Finalizable {}
+
+int doSomething() => 3;
+
+Stream<int> useFinalizableAsyncStar(Finalizable finalizable) async* {
+ final finalizable2 = MyFinalizable();
+ yield doSomething();
+ final finalizable3 = MyFinalizable();
+ await Future.sync(() => 3);
+ final finalizable4 = MyFinalizable();
+ if (DateTime.now().millisecondsSinceEpoch == 4) {
+ return;
+ }
+ yield 5;
+}
+
+void main() async {
+ final finalizable = MyFinalizable();
+ final asyncStarResult = useFinalizableAsyncStar(finalizable);
+ await for (final element in asyncStarResult) {
+ print(element);
+ }
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart.expect
new file mode 100644
index 0000000..01a6c61
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart.expect
@@ -0,0 +1,141 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+ synthetic constructor •() → self::MyFinalizable
+ : super core::Object::•()
+ ;
+}
+static method doSomething() → core::int
+ return 3;
+static method useFinalizableAsyncStar(ffi::Finalizable finalizable) → asy::Stream<core::int> /* originally async* */ {
+ asy::_AsyncStarStreamController<core::int>? :controller;
+ dynamic :controller_stream;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ dynamic :saved_try_context_var1;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try
+ try {
+ #L1:
+ {
+ final self::MyFinalizable finalizable2 = new self::MyFinalizable::•();
+ if([@vm.call-site-attributes.metadata=receiverType:dart.async::_AsyncStarStreamController<dart.core::int>?] :controller.{asy::_AsyncStarStreamController::add}( block {
+ final core::int :expressionValueWrappedFinalizable = self::doSomething();
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable2);
+ } =>:expressionValueWrappedFinalizable){(core::int) → core::bool})
+ return null;
+ else
+ [yield] null;
+ final self::MyFinalizable finalizable3 = new self::MyFinalizable::•();
+ [yield] let dynamic #t1 = asy::_awaitHelper( block {
+ final asy::Future<core::int> :expressionValueWrappedFinalizable = asy::Future::sync<core::int>(() → core::int => 3);
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable2);
+ _in::reachabilityFence(finalizable3);
+ } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::int>(:result);
+ final self::MyFinalizable finalizable4 = new self::MyFinalizable::•();
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 4) {
+ {
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable2);
+ _in::reachabilityFence(finalizable3);
+ _in::reachabilityFence(finalizable4);
+ break #L1;
+ }
+ }
+ if([@vm.call-site-attributes.metadata=receiverType:dart.async::_AsyncStarStreamController<dart.core::int>?] :controller.{asy::_AsyncStarStreamController::add}( block {
+ final core::int :expressionValueWrappedFinalizable = 5;
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable2);
+ _in::reachabilityFence(finalizable3);
+ _in::reachabilityFence(finalizable4);
+ } =>:expressionValueWrappedFinalizable){(core::int) → core::bool})
+ return null;
+ else
+ [yield] null;
+ _in::reachabilityFence(finalizable2);
+ _in::reachabilityFence(finalizable3);
+ _in::reachabilityFence(finalizable4);
+ _in::reachabilityFence(finalizable);
+ }
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ :controller.{asy::_AsyncStarStreamController::addError}(exception, stack_trace){(core::Object, core::StackTrace) → void};
+ }
+ finally {
+ :controller.{asy::_AsyncStarStreamController::close}(){() → dynamic};
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :controller = new asy::_AsyncStarStreamController::•<core::int>(:async_op);
+ :controller_stream = :controller.{asy::_AsyncStarStreamController::stream}{asy::Stream<core::int>};
+ return :controller_stream;
+}
+static method main() → void /* originally async */ {
+ final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
+ core::bool* :is_sync = false;
+ dynamic :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ dynamic :saved_try_context_var1;
+ dynamic :exception0;
+ dynamic :stack_trace0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ final self::MyFinalizable finalizable = new self::MyFinalizable::•();
+ final asy::Stream<core::int> asyncStarResult = self::useFinalizableAsyncStar(finalizable);
+ {
+ asy::Stream<core::int> :stream = asyncStarResult;
+ asy::_StreamIterator<core::int>? :for-iterator = new asy::_StreamIterator::•<core::int>(:stream);
+ try
+ #L3:
+ while (true) {
+ dynamic #t2 = asy::_asyncStarMoveNextHelper(:stream);
+ [yield] let dynamic #t3 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(){() → asy::Future<core::bool>}, :async_op_then, :async_op_error, :async_op) in null;
+ if(_in::unsafeCast<core::bool>(:result)) {
+ final core::int element = :for-iterator.{asy::_StreamIterator::current}{core::int};
+ {
+ core::print(element);
+ }
+ }
+ else
+ break #L3;
+ }
+ finally
+ if(!(:for-iterator.{asy::_StreamIterator::_subscription}{asy::StreamSubscription<core::int>?} == null)) {
+ [yield] let dynamic #t4 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(){() → asy::Future<dynamic>}, :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ }
+ }
+ _in::reachabilityFence(finalizable);
+ }
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+ asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_op(){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart b/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart
new file mode 100644
index 0000000..1735d18
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.16
+
+import 'dart:ffi';
+
+int doSomething() => 3;
+
+class MyFinalizable implements Finalizable {
+ int use() {
+ return doSomething();
+ }
+}
+
+/// Should be transformed into:
+///
+/// ```
+/// int useFinalizableSync(Finalizable finalizable) {
+/// final result = doSomething();
+/// _reachabilityFence(finalizable);
+/// return result;
+/// }
+/// ```
+int useFinalizableSync(Finalizable finalizable) {
+ return doSomething();
+}
+
+/// Should be transformed into:
+///
+/// ```
+/// void main() {
+/// final finalizable = MyFinalizable();
+/// print(useFinalizableSync(finalizable));
+/// _reachabilityFence(finalizable);
+/// }
+/// ```
+void main() {
+ final finalizable = MyFinalizable();
+ print(useFinalizableSync(finalizable));
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart.expect
new file mode 100644
index 0000000..45da19f
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart.expect
@@ -0,0 +1,32 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+ synthetic constructor •() → self::MyFinalizable
+ : super core::Object::•()
+ ;
+ method use() → core::int {
+ return block {
+ final core::int :expressionValueWrappedFinalizable = self::doSomething();
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ }
+}
+static method doSomething() → core::int
+ return 3;
+static method useFinalizableSync(ffi::Finalizable finalizable) → core::int {
+ return block {
+ final core::int :expressionValueWrappedFinalizable = self::doSomething();
+ _in::reachabilityFence(finalizable);
+ } =>:expressionValueWrappedFinalizable;
+}
+static method main() → void {
+ final self::MyFinalizable finalizable = new self::MyFinalizable::•();
+ core::print(self::useFinalizableSync(finalizable));
+ _in::reachabilityFence(finalizable);
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart b/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart
new file mode 100644
index 0000000..b435be9
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart
@@ -0,0 +1,227 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.16
+
+// ignore_for_file: unused_local_variable
+
+import 'dart:ffi';
+
+class MyFinalizable implements Finalizable {
+ int internalValue = 4;
+}
+
+void main() {
+ final finalizable = MyFinalizable();
+ {
+ final finalizable2 = MyFinalizable();
+ // Should generate: _reachabilityFence(finalizable2);
+ }
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ // Should generate: _reachabilityFence(finalizable1);
+ return;
+ } else {
+ try {
+ final finalizable3 = MyFinalizable();
+ {
+ // Should not generate anything.
+ }
+ // Should generate: _reachabilityFence(finalizable3);
+ } on Exception {
+ final finalizable4 = MyFinalizable();
+ // Should generate: _reachabilityFence(finalizable4);
+ } finally {
+ final finalizable5 = MyFinalizable();
+ // Should generate: _reachabilityFence(finalizable5);
+ }
+ try {
+ final finalizable13 = MyFinalizable();
+ try {
+ final finalizable14 = MyFinalizable();
+ if (DateTime.now().millisecondsSinceEpoch == 100) {
+ // Caught in try.
+ // Should generate: _reachabilityFence(finalizable14);
+ throw Exception('foo');
+ }
+ if (DateTime.now().millisecondsSinceEpoch == 101) {
+ // Not caught in try.
+ // Should generate: _reachabilityFence(finalizable1);
+ // Should generate: _reachabilityFence(finalizable13);
+ // Should generate: _reachabilityFence(finalizable14);
+ throw Error();
+ }
+ } on Exception catch (e) {
+ print(e);
+ // Caught in surrounding try.
+ // Should generate: _reachabilityFence(finalizable13);
+ rethrow;
+ } finally {
+ if (DateTime.now().millisecondsSinceEpoch == 1000) {
+ // Caught in surrounding try.
+ // Should generate: _reachabilityFence(finalizable13);
+ throw Exception('bar');
+ }
+ }
+ // Should generate: _reachabilityFence(finalizable13);
+ } on Exception catch (e) {
+ print(e);
+ }
+ }
+ switch (DateTime.now().millisecondsSinceEpoch) {
+ case 1:
+ case 2:
+ final finalizable6 = MyFinalizable();
+ // Should generate: _reachabilityFence(finalizable1);
+ // Should generate: _reachabilityFence(finalizable6);
+ return;
+ Foo:
+ case 3:
+ final finalizable7 = MyFinalizable();
+ // Should generate: _reachabilityFence(finalizable7);
+ break;
+ Bar:
+ case 4:
+ final finalizable70 = MyFinalizable();
+ switch (DateTime.now().millisecondsSinceEpoch) {
+ case 5:
+ final finalizable71 = MyFinalizable();
+ if (DateTime.now().millisecondsSinceEpoch == 44) {
+ // Should generate: _reachabilityFence(finalizable70);
+ // Should generate: _reachabilityFence(finalizable71);
+ continue Bar;
+ }
+ // Should generate: _reachabilityFence(finalizable71);
+ break;
+ }
+ // Should generate: _reachabilityFence(finalizable70);
+ continue Foo;
+ default:
+ final finalizable8 = MyFinalizable();
+ // Should generate: _reachabilityFence(finalizable8);
+ }
+ labelI:
+ labelI3:
+ for (int i = 0; i < 10; i++) {
+ final finalizable9 = MyFinalizable();
+ labelJ:
+ for (int j = 0; j < 10; j++) {
+ final finalizable10 = MyFinalizable();
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ // Should generate: _reachabilityFence(finalizable9);
+ // Should generate: _reachabilityFence(finalizable10);
+ break labelI3;
+ }
+ if (DateTime.now().millisecondsSinceEpoch == 1337) {
+ // Should generate: _reachabilityFence(finalizable9);
+ // Should generate: _reachabilityFence(finalizable10);
+ break labelI;
+ }
+ if (DateTime.now().millisecondsSinceEpoch == 1) {
+ // Should generate: _reachabilityFence(finalizable9);
+ continue labelJ;
+ }
+ if (DateTime.now().millisecondsSinceEpoch == 3) {
+ // Should generate: _reachabilityFence(finalizable9);
+ // Should generate: _reachabilityFence(finalizable10);
+ continue labelI;
+ }
+ // Should generate: _reachabilityFence(finalizable10);
+ }
+ // Should generate: _reachabilityFence(finalizable9);
+ }
+ label1:
+ {
+ final finalizable11 = MyFinalizable();
+ label2:
+ {
+ final finalizable12 = MyFinalizable();
+ if (DateTime.now().millisecondsSinceEpoch == 1) {
+ // Should generate: _reachabilityFence(finalizable11);
+ // Should generate: _reachabilityFence(finalizable12);
+ break label1;
+ }
+ if (DateTime.now().millisecondsSinceEpoch == 3) {
+ // Should generate: _reachabilityFence(finalizable12);
+ break label2;
+ }
+ // Should generate: _reachabilityFence(finalizable12);
+ }
+ // Should generate: _reachabilityFence(finalizable11);
+ }
+ for (int i = 0; i < 10; i++) {
+ final finalizable15 = MyFinalizable();
+ // Should generate: _reachabilityFence(finalizable15);
+ }
+ int i = 0;
+ while (i < 10) {
+ final finalizable16 = MyFinalizable();
+ i++;
+ // Should generate: _reachabilityFence(finalizable16);
+ }
+ for (final finalizable17
+ in Iterable<Finalizable>.generate(5, (int index) => MyFinalizable())) {
+ // Should generate: _reachabilityFence(finalizable17);
+ }
+ i = 0;
+ for (Finalizable finalizable18 = MyFinalizable(); i < 10; i++) {
+ // Should generate: _reachabilityFence(finalizable18);
+ }
+ // Should generate: _reachabilityFence(finalizable1);
+}
+
+int doSomething(int a) => a;
+
+void Function() createClosure() {
+ final finalizable20 = MyFinalizable();
+ return () {
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return;
+ // Should generate: _reachabilityFence(finalizable20);
+ }
+ doSomething(finalizable20.internalValue);
+ // Should generate: _reachabilityFence(finalizable20);
+ };
+ // Should generate: _reachabilityFence(finalizable20);
+}
+
+void Function() Function() Function() createNestedClosure() {
+ final finalizable40 = MyFinalizable();
+ return () {
+ final finalizable41 = MyFinalizable();
+ return () {
+ final finalizable42 = MyFinalizable();
+ return () {
+ doSomething(finalizable40.internalValue);
+ doSomething(finalizable41.internalValue);
+ doSomething(finalizable42.internalValue);
+ // Should generate: _reachabilityFence(finalizable40);
+ // Should generate: _reachabilityFence(finalizable41);
+ // Should generate: _reachabilityFence(finalizable42);
+ };
+ // Should generate: _reachabilityFence(finalizable40);
+ // Should generate: _reachabilityFence(finalizable41);
+ // Should generate: _reachabilityFence(finalizable42);
+ };
+ // Should generate: _reachabilityFence(finalizable40);
+ // Should generate: _reachabilityFence(finalizable41);
+ };
+ // Should generate: _reachabilityFence(finalizable40);
+}
+
+void Function() createBadClosure() {
+ final finalizable21 = MyFinalizable();
+ final internalValue = finalizable21.internalValue;
+ return () {
+ doSomething(internalValue);
+ // Should not generate: _reachabilityFence(finalizable21);
+ };
+ // Should generate: _reachabilityFence(finalizable21);
+}
+
+void reassignment() {
+ var finalizable30 = MyFinalizable();
+ doSomething(4);
+ // Should generate: _reachabilityFence(finalizable30);
+ finalizable30 = MyFinalizable();
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart.expect
new file mode 100644
index 0000000..987ce3e
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart.expect
@@ -0,0 +1,300 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+ field core::int internalValue = 4;
+ synthetic constructor •() → self::MyFinalizable
+ : super core::Object::•()
+ ;
+}
+static method main() → void {
+ final self::MyFinalizable finalizable = new self::MyFinalizable::•();
+ {
+ final self::MyFinalizable finalizable2 = new self::MyFinalizable::•();
+ _in::reachabilityFence(finalizable2);
+ }
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+ {
+ _in::reachabilityFence(finalizable);
+ return;
+ }
+ }
+ else {
+ try
+ try {
+ final self::MyFinalizable finalizable3 = new self::MyFinalizable::•();
+ {}
+ _in::reachabilityFence(finalizable3);
+ }
+ on core::Exception catch(no-exception-var) {
+ final self::MyFinalizable finalizable4 = new self::MyFinalizable::•();
+ _in::reachabilityFence(finalizable4);
+ }
+ finally {
+ final self::MyFinalizable finalizable5 = new self::MyFinalizable::•();
+ _in::reachabilityFence(finalizable5);
+ }
+ try {
+ final self::MyFinalizable finalizable13 = new self::MyFinalizable::•();
+ try
+ try {
+ final self::MyFinalizable finalizable14 = new self::MyFinalizable::•();
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 100) {
+ throw block {
+ final core::Exception :expressionValueWrappedFinalizable = core::Exception::•("foo");
+ _in::reachabilityFence(finalizable14);
+ } =>:expressionValueWrappedFinalizable;
+ }
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 101) {
+ throw block {
+ final core::Error :expressionValueWrappedFinalizable = new core::Error::•();
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable13);
+ _in::reachabilityFence(finalizable14);
+ } =>:expressionValueWrappedFinalizable;
+ }
+ _in::reachabilityFence(finalizable14);
+ }
+ on core::Exception catch(final core::Exception e) {
+ core::print(e);
+ block {
+ _in::reachabilityFence(finalizable13);
+ } =>rethrow;
+ }
+ finally {
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 1000) {
+ throw block {
+ final core::Exception :expressionValueWrappedFinalizable = core::Exception::•("bar");
+ _in::reachabilityFence(finalizable13);
+ } =>:expressionValueWrappedFinalizable;
+ }
+ }
+ _in::reachabilityFence(finalizable13);
+ }
+ on core::Exception catch(final core::Exception e) {
+ core::print(e);
+ }
+ }
+ #L1:
+ switch(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int}) {
+ #L2:
+ case #C1:
+ case #C2:
+ {
+ final self::MyFinalizable finalizable6 = new self::MyFinalizable::•();
+ {
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable6);
+ return;
+ }
+ }
+ #L3:
+ case #C3:
+ {
+ final self::MyFinalizable finalizable7 = new self::MyFinalizable::•();
+ {
+ _in::reachabilityFence(finalizable7);
+ break #L1;
+ }
+ }
+ #L4:
+ case #C4:
+ {
+ final self::MyFinalizable finalizable70 = new self::MyFinalizable::•();
+ #L5:
+ switch(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int}) {
+ #L6:
+ case #C5:
+ {
+ final self::MyFinalizable finalizable71 = new self::MyFinalizable::•();
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 44) {
+ {
+ _in::reachabilityFence(finalizable70);
+ _in::reachabilityFence(finalizable71);
+ continue #L4;
+ }
+ }
+ {
+ _in::reachabilityFence(finalizable71);
+ break #L5;
+ }
+ }
+ }
+ {
+ _in::reachabilityFence(finalizable70);
+ continue #L3;
+ }
+ }
+ #L7:
+ default:
+ {
+ final self::MyFinalizable finalizable8 = new self::MyFinalizable::•();
+ _in::reachabilityFence(finalizable8);
+ }
+ }
+ #L8:
+ for (core::int i = 0; i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int})
+ #L9:
+ {
+ final self::MyFinalizable finalizable9 = new self::MyFinalizable::•();
+ for (core::int j = 0; j.{core::num::<}(10){(core::num) → core::bool}; j = j.{core::num::+}(1){(core::num) → core::int})
+ #L10:
+ {
+ final self::MyFinalizable finalizable10 = new self::MyFinalizable::•();
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+ {
+ _in::reachabilityFence(finalizable9);
+ _in::reachabilityFence(finalizable10);
+ break #L8;
+ }
+ }
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 1337) {
+ {
+ _in::reachabilityFence(finalizable9);
+ _in::reachabilityFence(finalizable10);
+ break #L8;
+ }
+ }
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 1) {
+ {
+ _in::reachabilityFence(finalizable10);
+ break #L10;
+ }
+ }
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 3) {
+ {
+ _in::reachabilityFence(finalizable9);
+ _in::reachabilityFence(finalizable10);
+ break #L9;
+ }
+ }
+ _in::reachabilityFence(finalizable10);
+ }
+ _in::reachabilityFence(finalizable9);
+ }
+ #L11:
+ {
+ final self::MyFinalizable finalizable11 = new self::MyFinalizable::•();
+ #L12:
+ {
+ final self::MyFinalizable finalizable12 = new self::MyFinalizable::•();
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 1) {
+ {
+ _in::reachabilityFence(finalizable11);
+ _in::reachabilityFence(finalizable12);
+ break #L11;
+ }
+ }
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 3) {
+ {
+ _in::reachabilityFence(finalizable12);
+ break #L12;
+ }
+ }
+ _in::reachabilityFence(finalizable12);
+ }
+ _in::reachabilityFence(finalizable11);
+ }
+ for (core::int i = 0; i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int}) {
+ final self::MyFinalizable finalizable15 = new self::MyFinalizable::•();
+ _in::reachabilityFence(finalizable15);
+ }
+ core::int i = 0;
+ while (i.{core::num::<}(10){(core::num) → core::bool}) {
+ final self::MyFinalizable finalizable16 = new self::MyFinalizable::•();
+ i = i.{core::num::+}(1){(core::num) → core::int};
+ _in::reachabilityFence(finalizable16);
+ }
+ {
+ core::Iterator<ffi::Finalizable> :sync-for-iterator = core::Iterable::generate<ffi::Finalizable>(5, (core::int index) → self::MyFinalizable => new self::MyFinalizable::•()).{core::Iterable::iterator}{core::Iterator<ffi::Finalizable>};
+ for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
+ final ffi::Finalizable finalizable17 = :sync-for-iterator.{core::Iterator::current}{ffi::Finalizable};
+ {
+ _in::reachabilityFence(finalizable17);
+ }
+ }
+ }
+ i = 0;
+ for (ffi::Finalizable finalizable18 = new self::MyFinalizable::•(); i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int}) {
+ _in::reachabilityFence(finalizable18);
+ }
+ _in::reachabilityFence(finalizable);
+}
+static method doSomething(core::int a) → core::int
+ return a;
+static method createClosure() → () → void {
+ final self::MyFinalizable finalizable20 = new self::MyFinalizable::•();
+ return block {
+ final () → void :expressionValueWrappedFinalizable = () → void {
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+ {
+ _in::reachabilityFence(finalizable20);
+ return;
+ }
+ }
+ self::doSomething(finalizable20.{self::MyFinalizable::internalValue}{core::int});
+ _in::reachabilityFence(finalizable20);
+ };
+ _in::reachabilityFence(finalizable20);
+ } =>:expressionValueWrappedFinalizable;
+}
+static method createNestedClosure() → () → () → () → void {
+ final self::MyFinalizable finalizable40 = new self::MyFinalizable::•();
+ return block {
+ final () → () → () → void :expressionValueWrappedFinalizable = () → () → () → void {
+ final self::MyFinalizable finalizable41 = new self::MyFinalizable::•();
+ return block {
+ final () → () → void :expressionValueWrappedFinalizable = () → () → void {
+ final self::MyFinalizable finalizable42 = new self::MyFinalizable::•();
+ return block {
+ final () → void :expressionValueWrappedFinalizable = () → void {
+ self::doSomething(finalizable40.{self::MyFinalizable::internalValue}{core::int});
+ self::doSomething(finalizable41.{self::MyFinalizable::internalValue}{core::int});
+ self::doSomething(finalizable42.{self::MyFinalizable::internalValue}{core::int});
+ _in::reachabilityFence(finalizable40);
+ _in::reachabilityFence(finalizable41);
+ _in::reachabilityFence(finalizable42);
+ };
+ _in::reachabilityFence(finalizable40);
+ _in::reachabilityFence(finalizable41);
+ _in::reachabilityFence(finalizable42);
+ } =>:expressionValueWrappedFinalizable;
+ };
+ _in::reachabilityFence(finalizable40);
+ _in::reachabilityFence(finalizable41);
+ } =>:expressionValueWrappedFinalizable;
+ };
+ _in::reachabilityFence(finalizable40);
+ } =>:expressionValueWrappedFinalizable;
+}
+static method createBadClosure() → () → void {
+ final self::MyFinalizable finalizable21 = new self::MyFinalizable::•();
+ final core::int internalValue = finalizable21.{self::MyFinalizable::internalValue}{core::int};
+ return block {
+ final () → void :expressionValueWrappedFinalizable = () → void {
+ self::doSomething(internalValue);
+ };
+ _in::reachabilityFence(finalizable21);
+ } =>:expressionValueWrappedFinalizable;
+}
+static method reassignment() → void {
+ self::MyFinalizable finalizable30 = new self::MyFinalizable::•();
+ self::doSomething(4);
+ finalizable30 = block {
+ final self::MyFinalizable :expressionValueWrappedFinalizable = new self::MyFinalizable::•();
+ _in::reachabilityFence(finalizable30);
+ } =>:expressionValueWrappedFinalizable;
+ _in::reachabilityFence(finalizable30);
+}
+constants {
+ #C1 = 1
+ #C2 = 2
+ #C3 = 3
+ #C4 = 4
+ #C5 = 5
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart b/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart
new file mode 100644
index 0000000..bc83bbe
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.16
+
+// ignore_for_file: unused_local_variable
+
+import 'dart:ffi';
+
+class MyFinalizable implements Finalizable {
+ int _internalValue = 4;
+
+ int Function() capturingThis() {
+ return () {
+ final result = this._internalValue;
+ // Should generate: _reachabilityFence(this)
+ return result;
+ };
+ // Should generate: _reachabilityFence(this)
+ }
+
+ int Function() capturingThis2() {
+ return () {
+ return this._internalValue;
+ // Should generate: _reachabilityFence(this)
+ };
+ // Should generate: _reachabilityFence(this)
+ }
+
+ int Function() capturingThis3() {
+ return () {
+ return _internalValue;
+ // Should generate: _reachabilityFence(this)
+ };
+ // Should generate: _reachabilityFence(this)
+ }
+
+ /// Tests that captures later in the body also cause fences earlier in the body.
+ int Function() capturingThis4() {
+ return () {
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ // Should generate: _reachabilityFence(this)
+ return 3;
+ }
+ return _internalValue;
+ // Should generate: _reachabilityFence(this)
+ };
+ // Should generate: _reachabilityFence(this)
+ }
+}
+
+void main() {}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart.expect
new file mode 100644
index 0000000..c251fa6
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart.expect
@@ -0,0 +1,66 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+ field core::int _internalValue = 4;
+ synthetic constructor •() → self::MyFinalizable
+ : super core::Object::•()
+ ;
+ method capturingThis() → () → core::int {
+ return block {
+ final () → core::int :expressionValueWrappedFinalizable = () → core::int {
+ final core::int result = this.{self::MyFinalizable::_internalValue}{core::int};
+ return block {
+ final core::int :expressionValueWrappedFinalizable = result;
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ };
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ }
+ method capturingThis2() → () → core::int {
+ return block {
+ final () → core::int :expressionValueWrappedFinalizable = () → core::int {
+ return block {
+ final core::int :expressionValueWrappedFinalizable = this.{self::MyFinalizable::_internalValue}{core::int};
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ };
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ }
+ method capturingThis3() → () → core::int {
+ return block {
+ final () → core::int :expressionValueWrappedFinalizable = () → core::int {
+ return block {
+ final core::int :expressionValueWrappedFinalizable = this.{self::MyFinalizable::_internalValue}{core::int};
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ };
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ }
+ method capturingThis4() → () → core::int {
+ return block {
+ final () → core::int :expressionValueWrappedFinalizable = () → core::int {
+ if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+ return block {
+ final core::int :expressionValueWrappedFinalizable = 3;
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ }
+ return block {
+ final core::int :expressionValueWrappedFinalizable = this.{self::MyFinalizable::_internalValue}{core::int};
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ };
+ _in::reachabilityFence(this);
+ } =>:expressionValueWrappedFinalizable;
+ }
+}
+static method main() → void {}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart b/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart
new file mode 100644
index 0000000..535486f
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.16
+
+// ignore_for_file: unused_local_variable
+
+import 'dart:ffi';
+
+class MyFinalizable implements Finalizable {}
+
+int doSomething() => 3;
+
+Iterable<int> useFinalizableSyncStar(Finalizable finalizable) sync* {
+ // _in::reachabilityFence(finalizable);
+ yield doSomething();
+ final finalizable2 = MyFinalizable();
+ // _in::reachabilityFence(finalizable);
+ // _in::reachabilityFence(finalizable2);
+ yield 5;
+ final finalizable3 = MyFinalizable();
+ // _in::reachabilityFence(finalizable);
+ // _in::reachabilityFence(finalizable2);
+ // _in::reachabilityFence(finalizable3);
+ yield 10;
+ // _in::reachabilityFence(finalizable);
+ // _in::reachabilityFence(finalizable2);
+ // _in::reachabilityFence(finalizable3);
+}
+
+void main() {
+ final finalizable = MyFinalizable();
+ for (final element in useFinalizableSyncStar(finalizable)) {
+ print(element);
+ }
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart.expect
new file mode 100644
index 0000000..fc74d17
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart.expect
@@ -0,0 +1,71 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+ synthetic constructor •() → self::MyFinalizable
+ : super core::Object::•()
+ ;
+}
+static method doSomething() → core::int
+ return 3;
+static method useFinalizableSyncStar(ffi::Finalizable finalizable) → core::Iterable<core::int> /* originally sync* */ {
+ function :sync_op_gen() → (core::_SyncIterator<dynamic>?, dynamic, dynamic) → core::bool* {
+ core::int :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ ffi::Finalizable finalizable = finalizable;
+ function :sync_op(core::_SyncIterator<dynamic>? :iterator, dynamic :exception, dynamic :stack_trace) → core::bool* yielding {
+ {
+ {
+ [@vm.call-site-attributes.metadata=receiverType:dart.core::_SyncIterator<dynamic>?] :iterator.{core::_SyncIterator::_current} = block {
+ final core::int :expressionValueWrappedFinalizable = self::doSomething();
+ _in::reachabilityFence(finalizable);
+ } =>:expressionValueWrappedFinalizable;
+ [yield] true;
+ }
+ final self::MyFinalizable finalizable2 = new self::MyFinalizable::•();
+ {
+ [@vm.call-site-attributes.metadata=receiverType:dart.core::_SyncIterator<dynamic>?] :iterator.{core::_SyncIterator::_current} = block {
+ final core::int :expressionValueWrappedFinalizable = 5;
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable2);
+ } =>:expressionValueWrappedFinalizable;
+ [yield] true;
+ }
+ final self::MyFinalizable finalizable3 = new self::MyFinalizable::•();
+ {
+ [@vm.call-site-attributes.metadata=receiverType:dart.core::_SyncIterator<dynamic>?] :iterator.{core::_SyncIterator::_current} = block {
+ final core::int :expressionValueWrappedFinalizable = 10;
+ _in::reachabilityFence(finalizable);
+ _in::reachabilityFence(finalizable2);
+ _in::reachabilityFence(finalizable3);
+ } =>:expressionValueWrappedFinalizable;
+ [yield] true;
+ }
+ _in::reachabilityFence(finalizable2);
+ _in::reachabilityFence(finalizable3);
+ _in::reachabilityFence(finalizable);
+ }
+ return false;
+ }
+ return :sync_op;
+ }
+ return new core::_SyncIterable::•<core::int>(:sync_op_gen);
+}
+static method main() → void {
+ final self::MyFinalizable finalizable = new self::MyFinalizable::•();
+ {
+ core::Iterator<core::int> :sync-for-iterator = self::useFinalizableSyncStar(finalizable).{core::Iterable::iterator}{core::Iterator<core::int>};
+ for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
+ final core::int element = :sync-for-iterator.{core::Iterator::current}{core::int};
+ {
+ core::print(element);
+ }
+ }
+ }
+ _in::reachabilityFence(finalizable);
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
index fc5a260..0f8f453 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
@@ -45,7 +45,7 @@
static method baz() → asy::Future<dynamic> /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
:return_value = new self::B::•();
break #L2;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -72,7 +72,7 @@
static method main() → dynamic /* originally async */ {
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>? :return_value;
+ dynamic :return_value;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
@@ -88,7 +88,7 @@
[yield] let dynamic #t2 = asy::_awaitHelper([@vm.direct-call.metadata=#lib::A.bar??] [@vm.inferred-type.metadata=dart.async::_Future<dynamic> (receiver not int)] :async_temporary_0{dynamic}.bar(:result), :async_op_then, :async_op_error, :async_op) in null;
:result;
}
- asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
index 9c9d0a4..950e802 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
@@ -22,6 +22,6 @@
synthetic constructor •() → self::Class
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3395,getterSelectorId:3396] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3399,getterSelectorId:3400] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
index c4d4faf..5ccaefa 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
@@ -51,6 +51,6 @@
synthetic constructor •() → self::ConstClass
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3399,getterSelectorId:3400] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3403,getterSelectorId:3404] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
}
diff --git a/pkg/vm_service/java/src/org/dartlang/vm/service/element/Element.java b/pkg/vm_service/java/src/org/dartlang/vm/service/element/Element.java
index cdee4bd..7fc05db 100644
--- a/pkg/vm_service/java/src/org/dartlang/vm/service/element/Element.java
+++ b/pkg/vm_service/java/src/org/dartlang/vm/service/element/Element.java
@@ -92,7 +92,8 @@
int size = array.size();
List<String> result = new ArrayList<>();
for (int index = 0; index < size; ++index) {
- result.add(array.get(index).getAsString());
+ final JsonElement elem = array.get(index);
+ result.add(elem == JsonNull.INSTANCE ? null : elem.getAsString());
}
return result;
}
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 4905a0d..f22ff9d 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -3420,7 +3420,7 @@
}
/// A `Code` object represents compiled code in the Dart VM.
-class Code extends ObjRef implements CodeRef {
+class Code extends Obj implements CodeRef {
static Code? parse(Map<String, dynamic>? json) =>
json == null ? null : Code._fromJson(json);
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 99c5e18..dc91e52 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -14,6 +14,7 @@
dev_dependencies:
async: ^2.5.0
+ expect: any
markdown: ^4.0.0-nullsafety.0
mockito: ^5.0.0-nullsafety.1
path: ^1.8.0
diff --git a/pkg/vm_service/test/causal_async_stack_contents_test.dart b/pkg/vm_service/test/causal_async_stack_contents_test.dart
new file mode 100644
index 0000000..b634f10
--- /dev/null
+++ b/pkg/vm_service/test/causal_async_stack_contents_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2017, 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.
+//
+// VMOptions=--lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const LINE_C = 20;
+const LINE_A = 26;
+const LINE_B = 32;
+
+foobar() {
+ debugger();
+ print('foobar'); // LINE_C.
+}
+
+helper() async {
+ await 0; // force async gap
+ debugger();
+ print('helper'); // LINE_A.
+ foobar();
+}
+
+testMain() {
+ debugger();
+ helper(); // LINE_B.
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_B),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // No causal frames because we are in a completely synchronous stack.
+ expect(stack.asyncCausalFrames, isNull);
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_A),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // Has causal frames (we are inside an async function)
+ expect(stack.asyncCausalFrames, isNotNull);
+ expect(
+ stack.asyncCausalFrames![0].function!.owner.name,
+ contains('helper'),
+ );
+ // "helper" is not await'ed.
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_C),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // Has causal frames (we are inside a function called by an async function)
+ expect(stack.asyncCausalFrames, isNotNull);
+ final asyncStack = stack.asyncCausalFrames!;
+ expect(asyncStack[0].function!.name, contains('foobar'));
+ expect(asyncStack[1].function!.owner.name, contains('helper'));
+ // "helper" is not await'ed.
+ },
+];
+
+main(args) => runIsolateTestsSynchronous(
+ args,
+ tests,
+ 'causal_async_stack_contents_test.dart',
+ testeeConcurrent: testMain,
+ extraArgs: extraDebuggingArgs,
+ );
diff --git a/pkg/vm_service/test/causal_async_stack_presence_test.dart b/pkg/vm_service/test/causal_async_stack_presence_test.dart
new file mode 100644
index 0000000..48bf16e
--- /dev/null
+++ b/pkg/vm_service/test/causal_async_stack_presence_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2017, 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.
+//
+// VMOptions=--lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const LINE_C = 19;
+const LINE_A = 25;
+const LINE_B = 31;
+
+foobar() {
+ debugger();
+ print('foobar'); // LINE_C.
+}
+
+helper() async {
+ await 0; // Yield. The rest will run async.
+ debugger();
+ print('helper'); // LINE_A.
+ foobar();
+}
+
+testMain() {
+ debugger();
+ helper(); // LINE_B.
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_B),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // No causal frames because we are in a completely synchronous stack.
+ // Async function hasn't yielded yet.
+ expect(stack.asyncCausalFrames, isNull);
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_A),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // Async function has yielded once, so it's now running async.
+ expect(stack.asyncCausalFrames, isNotNull);
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_C),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // Has causal frames (we are inside a function called by an async function)
+ expect(stack.asyncCausalFrames, isNotNull);
+ },
+];
+
+main(args) => runIsolateTestsSynchronous(
+ args,
+ tests,
+ 'causal_async_stack_presence_test.dart',
+ testeeConcurrent: testMain,
+ extraArgs: extraDebuggingArgs,
+ );
diff --git a/pkg/vm_service/test/causal_async_star_stack_contents_test.dart b/pkg/vm_service/test/causal_async_star_stack_contents_test.dart
new file mode 100644
index 0000000..4795850
--- /dev/null
+++ b/pkg/vm_service/test/causal_async_star_stack_contents_test.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2017, 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.
+//
+// VMOptions=--lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const LINE_A = 29;
+const LINE_B = 21;
+const LINE_C = 23;
+
+foobar() async* {
+ await 0; // force async gap
+ debugger();
+ yield 1; // LINE_B.
+ debugger();
+ yield 2; // LINE_C.
+}
+
+helper() async {
+ await 0; // force async gap
+ debugger();
+ print('helper'); // LINE_A.
+ await for (var i in foobar()) {
+ print('helper $i');
+ }
+}
+
+testMain() {
+ helper();
+}
+
+final tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_A),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // No causal frames because we are in a completely synchronous stack.
+ expect(stack.asyncCausalFrames, isNotNull);
+ final asyncStack = stack.asyncCausalFrames!;
+ expect(asyncStack.length, greaterThanOrEqualTo(1));
+ expect(asyncStack[0].function!.owner.name, contains('helper'));
+ // helper isn't awaited.
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_B),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // Has causal frames (we are inside an async function)
+ expect(stack.asyncCausalFrames, isNotNull);
+ final asyncStack = stack.asyncCausalFrames!;
+ expect(asyncStack.length, greaterThanOrEqualTo(3));
+ expect(asyncStack[0].function!.owner.name, contains('foobar'));
+ expect(asyncStack[1].kind, equals(FrameKind.kAsyncSuspensionMarker));
+ expect(asyncStack[2].function!.owner.name, contains('helper'));
+ expect(asyncStack[3].kind, equals(FrameKind.kAsyncSuspensionMarker));
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_C),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // Has causal frames (we are inside a function called by an async function)
+ expect(stack.asyncCausalFrames, isNotNull);
+ final asyncStack = stack.asyncCausalFrames!;
+ expect(asyncStack.length, greaterThanOrEqualTo(4));
+ final script = await service.getObject(
+ isolateRef.id!, asyncStack[0].location!.script!.id!) as Script;
+ expect(asyncStack[0].function!.owner.name, contains('foobar'));
+ expect(
+ script.getLineNumberFromTokenPos(asyncStack[0].location!.tokenPos!),
+ LINE_C,
+ );
+ expect(asyncStack[1].kind, equals(FrameKind.kAsyncSuspensionMarker));
+ expect(asyncStack[2].function!.owner.name, contains('helper'));
+ expect(
+ script.getLineNumberFromTokenPos(asyncStack[2].location!.tokenPos!),
+ 30,
+ );
+ expect(asyncStack[3].kind, equals(FrameKind.kAsyncSuspensionMarker));
+ },
+];
+
+main(args) => runIsolateTestsSynchronous(
+ args,
+ tests,
+ 'causal_async_star_stack_contents_test.dart',
+ testeeConcurrent: testMain,
+ extraArgs: extraDebuggingArgs,
+ );
diff --git a/pkg/vm_service/test/causal_async_star_stack_presence_test.dart b/pkg/vm_service/test/causal_async_star_stack_presence_test.dart
new file mode 100644
index 0000000..5ba0a7d
--- /dev/null
+++ b/pkg/vm_service/test/causal_async_star_stack_presence_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2017, 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.
+//
+// VMOptions=--lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const LINE_A = 26;
+const LINE_B = 19;
+const LINE_C = 21;
+
+foobar() async* {
+ debugger();
+ yield 1; // LINE_B.
+ debugger();
+ yield 2; // LINE_C.
+}
+
+helper() async {
+ debugger();
+ print('helper'); // LINE_A.
+ await for (var i in foobar()) {
+ print('helper $i');
+ }
+}
+
+testMain() {
+ helper();
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_A),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // No causal frames because we are in a completely synchronous stack.
+ expect(stack.asyncCausalFrames, isNull);
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_B),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // Has causal frames (we are inside an async function)
+ expect(stack.asyncCausalFrames, isNotNull);
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_C),
+ (VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+ // Has causal frames (we are inside a function called by an async function)
+ expect(stack.asyncCausalFrames, isNotNull);
+ },
+];
+
+main(args) => runIsolateTestsSynchronous(
+ args,
+ tests,
+ 'causal_async_star_stack_presence_test.dart',
+ testeeConcurrent: testMain,
+ extraArgs: extraDebuggingArgs,
+ );
diff --git a/pkg/vm_service/test/code_test.dart b/pkg/vm_service/test/code_test.dart
new file mode 100644
index 0000000..3803827
--- /dev/null
+++ b/pkg/vm_service/test/code_test.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'common/test_helper.dart';
+
+int counter = 0;
+
+void funcB() {
+ counter++; // line 13
+ if (counter % 100000000 == 0) {
+ print(counter);
+ }
+}
+
+void funcA() {
+ funcB();
+}
+
+void testFunction() {
+ while (true) {
+ funcA();
+ }
+}
+
+var tests = <IsolateTest>[
+// Go to breakpoint at line 13.
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+ final rootLib =
+ await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+ // Set up a listener to wait for breakpoint events.
+ final completer = Completer<void>();
+
+ late final StreamSubscription subscription;
+ subscription = service.onDebugEvent.listen((event) async {
+ if (event.kind == EventKind.kPauseBreakpoint) {
+ print('Breakpoint reached');
+ await service.streamCancel(EventStreams.kDebug);
+ await subscription.cancel();
+ completer.complete();
+ }
+ });
+ await service.streamListen(EventStreams.kDebug);
+
+ // Add the breakpoint.
+ final script = rootLib.scripts![0];
+ final line = 13;
+ await service.addBreakpoint(isolateId, script.id!, line);
+ await completer.future; // Wait for breakpoint reached.
+ },
+
+// Inspect code objects for top two frames.
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ Stack stack = await service.getStack(isolateId);
+ // Make sure we are in the right place.
+ expect(stack.frames!.length, greaterThanOrEqualTo(3));
+ final frame0 = stack.frames![0];
+ final frame1 = stack.frames![1];
+ expect(frame0.function!.name, equals('funcB'));
+ expect(frame1.function!.name, equals('funcA'));
+ final codeId0 = frame0.code!.id!;
+ final codeId1 = frame1.code!.id!;
+
+ // Load code from frame 0.
+ Code code = await service.getObject(isolateId, codeId0) as Code;
+ expect(code.name, contains('funcB'));
+ expect(code.json!['_disassembly'], isNotNull);
+ expect(code.json!['_disassembly'].length, greaterThan(0));
+
+ // Load code from frame 0.
+ code = await service.getObject(isolateId, codeId1) as Code;
+ expect(code.type, equals('Code'));
+ expect(code.name, contains('funcA'));
+ expect(code.json!['_disassembly'], isNotNull);
+ expect(code.json!['_disassembly'].length, greaterThan(0));
+ },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+ args,
+ tests,
+ 'code_test.dart',
+ testeeConcurrent: testFunction,
+ );
diff --git a/pkg/vm_service/test/column_breakpoint_test.dart b/pkg/vm_service/test/column_breakpoint_test.dart
new file mode 100644
index 0000000..8989f0d
--- /dev/null
+++ b/pkg/vm_service/test/column_breakpoint_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+code() {
+ var b = [1, 2].map((i) => i == 0).toList();
+ print(b.length);
+}
+
+const int LINE = 9;
+const int COLUMN = 29;
+const String shortFile = "column_breakpoint_test.dart";
+const String breakpointFile =
+ "package:observatory_test_package/column_breakpoint_test.dart";
+
+List<String> stops = [];
+
+List<String> expected = [
+ "$shortFile:${LINE + 0}:23", // on 'i == 0'
+ "$shortFile:${LINE + 0}:23", // iterate twice
+ "$shortFile:${LINE + 1}:3" //on 'b.length'
+];
+
+var tests = <IsolateTest>[
+ hasPausedAtStart,
+ setBreakpointAtLineColumn(LINE, COLUMN), // on 'i == 0'
+ setBreakpointAtLineColumn(LINE + 1, 9), // on 'b.length'
+ resumeProgramRecordingStops(stops, false),
+ checkRecordedStops(stops, expected)
+];
+
+main(args) {
+ runIsolateTestsSynchronous(
+ args,
+ tests,
+ 'column_breakpoint_test.dart',
+ testeeConcurrent: code,
+ pause_on_start: true,
+ pause_on_exit: true,
+ );
+}
diff --git a/pkg/vm_service/test/common/service_test_common.dart b/pkg/vm_service/test/common/service_test_common.dart
index 6e84d16..268060a 100644
--- a/pkg/vm_service/test/common/service_test_common.dart
+++ b/pkg/vm_service/test/common/service_test_common.dart
@@ -142,6 +142,25 @@
};
}
+IsolateTest setBreakpointAtLineColumn(int line, int column) {
+ return (VmService service, IsolateRef isolateRef) async {
+ print("Setting breakpoint for line $line column $column");
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+ final lib =
+ await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+ ScriptRef script = lib.scripts!.firstWhere((s) => s.uri == lib.uri);
+ Breakpoint bpt = await service.addBreakpoint(
+ isolateId,
+ script.id!,
+ line,
+ column: column,
+ );
+ print("Breakpoint is $bpt");
+ expect(bpt, isNotNull);
+ };
+}
+
IsolateTest stoppedAtLine(int line) {
return (VmService service, IsolateRef isolateRef) async {
print("Checking we are at line $line");
@@ -211,6 +230,34 @@
}
}
+Future<void> resumeAndAwaitEvent(
+ VmService service,
+ IsolateRef isolateRef,
+ String streamId,
+ Function(Event) onEvent,
+) async {
+ final completer = Completer<void>();
+ late final StreamSubscription sub;
+ sub = service.onEvent(streamId).listen((event) async {
+ await onEvent(event);
+ await sub.cancel();
+ await service.streamCancel(streamId);
+ completer.complete();
+ });
+
+ await service.streamListen(streamId);
+ await service.resume(isolateRef.id!);
+ return completer.future;
+}
+
+IsolateTest resumeIsolateAndAwaitEvent(
+ String streamId,
+ Function(Event) onEvent,
+) {
+ return (VmService service, IsolateRef isolate) async =>
+ resumeAndAwaitEvent(service, isolate, streamId, onEvent);
+}
+
Future<void> stepOver(VmService service, IsolateRef isolateRef) async {
await service.streamListen(EventStreams.kDebug);
await _subscribeDebugStream(service);
@@ -242,14 +289,13 @@
subscription = service.onDebugEvent.listen((event) async {
if (event.kind == EventKind.kPauseBreakpoint) {
final stack = await service.getStack(isolateRef.id!);
- final frames = stack.frames!;
- expect(frames.length, greaterThanOrEqualTo(2));
+ expect(stack.frames!.length, greaterThanOrEqualTo(2));
String brokeAt =
- await _locationToString(service, isolateRef, frames[0]);
+ await _locationToString(service, isolateRef, stack.frames![0]);
if (includeCaller) {
brokeAt =
- '$brokeAt (${await _locationToString(service, isolateRef, frames[1])})';
+ '$brokeAt (${await _locationToString(service, isolateRef, stack.frames![1])})';
}
recordStops.add(brokeAt);
await service.resume(isolateRef.id!);
diff --git a/pkg/vm_service/test/common/test_helper.dart b/pkg/vm_service/test/common/test_helper.dart
index 62ced95..a5001d0 100644
--- a/pkg/vm_service/test/common/test_helper.dart
+++ b/pkg/vm_service/test/common/test_helper.dart
@@ -351,6 +351,8 @@
await service.streamListen(EventStreams.kIsolate);
+ await service.streamListen(EventStreams.kIsolate);
+
// The isolate may have started before we subscribed.
vm = await service.getVM();
if (vmIsolates.isNotEmpty) {
diff --git a/pkg/vm_service/test/contexts_test.dart b/pkg/vm_service/test/contexts_test.dart
new file mode 100644
index 0000000..4047e7a
--- /dev/null
+++ b/pkg/vm_service/test/contexts_test.dart
@@ -0,0 +1,151 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+// Make sure these variables are not removed by the tree shaker.
+@pragma("vm:entry-point")
+var cleanBlock;
+@pragma("vm:entry-point")
+var copyingBlock;
+@pragma("vm:entry-point")
+var fullBlock;
+@pragma("vm:entry-point")
+var fullBlockWithChain;
+
+Function genCleanBlock() {
+ block(x) => x;
+ return block;
+}
+
+Function genCopyingBlock() {
+ final x = 'I could be copied into the block';
+ block() => x;
+ return block;
+}
+
+Function genFullBlock() {
+ var x = 42; // I must captured in a context.
+ block() => x;
+ x++;
+ return block;
+}
+
+Function genFullBlockWithChain() {
+ var x = 420; // I must captured in a context.
+ outerBlock() {
+ var y = 4200;
+ innerBlock() => x + y;
+ y++;
+ return innerBlock;
+ }
+
+ x++;
+ return outerBlock();
+}
+
+void script() {
+ cleanBlock = genCleanBlock();
+ copyingBlock = genCopyingBlock();
+ fullBlock = genFullBlock();
+ fullBlockWithChain = genFullBlockWithChain();
+}
+
+var tests = <IsolateTest>[
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+ final lib =
+ await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+ final field = await service.getObject(
+ isolateId,
+ lib.variables!.singleWhere((v) => v.name == 'cleanBlock').id!,
+ ) as Field;
+
+ Instance block =
+ await service.getObject(isolateId, field.staticValue!.id!) as Instance;
+ expect(block.closureFunction, isNotNull);
+ expect(block.closureContext, isNull);
+ },
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+ final lib =
+ await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+ final field = await service.getObject(
+ isolateId,
+ lib.variables!.singleWhere((v) => v.name == 'copyingBlock').id!,
+ ) as Field;
+ Instance block =
+ await service.getObject(isolateId, field.staticValue!.id!) as Instance;
+
+ expect(block.closureContext, isNotNull);
+ expect(block.closureContext!.length, equals(1));
+ final ctxt = await service.getObject(isolateId, block.closureContext!.id!)
+ as Context;
+ expect(ctxt.variables!.single.value.kind, InstanceKind.kString);
+ expect(
+ ctxt.variables!.single.value.valueAsString,
+ 'I could be copied into the block',
+ );
+ expect(ctxt.parent, isNull);
+ },
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+ final lib =
+ await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+ final field = await service.getObject(
+ isolateId,
+ lib.variables!.singleWhere((v) => v.name == 'fullBlock').id!,
+ ) as Field;
+ Instance block =
+ await service.getObject(isolateId, field.staticValue!.id!) as Instance;
+
+ expect(block.closureContext, isNotNull);
+ expect(block.closureContext!.length, equals(1));
+ final ctxt = await service.getObject(isolateId, block.closureContext!.id!)
+ as Context;
+
+ expect(ctxt.variables!.single.value.kind, InstanceKind.kInt);
+ expect(ctxt.variables!.single.value.valueAsString, '43');
+ expect(ctxt.parent, isNull);
+ },
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+ final lib =
+ await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+ final field = await service.getObject(
+ isolateId,
+ lib.variables!.singleWhere((v) => v.name == 'fullBlockWithChain').id!,
+ ) as Field;
+ final block =
+ await service.getObject(isolateId, field.staticValue!.id!) as Instance;
+
+ expect(block.closureContext, isNotNull);
+ expect(block.closureContext!.length, equals(1));
+ final ctxt = await service.getObject(isolateId, block.closureContext!.id!)
+ as Context;
+ expect(ctxt.variables!.single.value.kind, InstanceKind.kInt);
+ expect(ctxt.variables!.single.value.valueAsString, '4201');
+ expect(ctxt.parent!.length, 1);
+
+ final outerCtxt =
+ await service.getObject(isolateId, ctxt.parent!.id!) as Context;
+ expect(outerCtxt.variables!.single.value.kind, InstanceKind.kInt);
+ expect(outerCtxt.variables!.single.value.valueAsString, '421');
+ expect(outerCtxt.parent, isNull);
+ },
+];
+
+main(args) => runIsolateTests(
+ args,
+ tests,
+ 'contexts_test.dart',
+ testeeBefore: script,
+ );
diff --git a/pkg/vm_service/test/coverage_const_field_async_closure_test.dart b/pkg/vm_service/test/coverage_const_field_async_closure_test.dart
new file mode 100644
index 0000000..8a7430d
--- /dev/null
+++ b/pkg/vm_service/test/coverage_const_field_async_closure_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const int LINE_A = 17; // LINE_A - 4
+const int LINE_B = 25; // LINE_A - 3
+
+class Bar {
+ static const String field = "field"; // LINE_A
+}
+
+Future<String> fooAsync(int x) async {
+ if (x == 42) {
+ return '*' * x;
+ }
+ return List.generate(x, (_) => 'xyzzy').join(' ');
+} // LINE_B
+
+Future<void> testFunction() async {
+ await Future.delayed(Duration(milliseconds: 500));
+ // ignore: unawaited_futures
+ fooAsync(42).then((_) {});
+ debugger();
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+ final stack = await service.getStack(isolateId);
+
+ // Make sure we are in the right place.
+ expect(stack.frames!.length, greaterThanOrEqualTo(1));
+ // Async closure of testFunction
+ expect(stack.frames![0].function!.name, 'async_op');
+
+ final rootLib =
+ await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+ final script = await service.getObject(
+ isolateId, rootLib.scripts!.first.id!) as Script;
+
+ final report = await service.getSourceReport(
+ isolateId,
+ ['Coverage'],
+ scriptId: script.id!,
+ forceCompile: true,
+ );
+ int match = 0;
+ for (var range in report.ranges!) {
+ for (int i in range.coverage!.hits!) {
+ int? line = script.getLineNumberFromTokenPos(i);
+ if (line == null) {
+ throw FormatException('token ${i} was missing source location');
+ }
+ // Check LINE.
+ if (line == LINE_A || line == LINE_A - 3 || line == LINE_A - 4) {
+ match = match + 1;
+ }
+ // _clearAsyncThreadStackTrace should have an invalid token position.
+ expect(line, isNot(LINE_B));
+ }
+ }
+ // Neither LINE nor Bar.field should be added into coverage.
+ expect(match, 0);
+ },
+ resumeIsolate
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+ args,
+ tests,
+ 'coverage_const_field_async_closure_test.dart',
+ testeeConcurrent: testFunction,
+ );
diff --git a/pkg/vm_service/test/coverage_leaf_function_test.dart b/pkg/vm_service/test/coverage_leaf_function_test.dart
index 36b9a88..95ec6f8 100644
--- a/pkg/vm_service/test/coverage_leaf_function_test.dart
+++ b/pkg/vm_service/test/coverage_leaf_function_test.dart
@@ -3,8 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:developer';
+
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
+
import 'common/service_test_common.dart';
import 'common/test_helper.dart';
@@ -38,7 +40,7 @@
expect(stack.frames!.length, greaterThanOrEqualTo(1));
expect(stack.frames![0].function!.name, 'testFunction');
- final Library root =
+ final root =
await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
FuncRef funcRef =
root.functions!.singleWhere((f) => f.name == 'leafFunction');
@@ -69,12 +71,12 @@
coverageTest(
{
'scriptIndex': 0,
- 'startPos': 397,
- 'endPos': 447,
+ 'startPos': 399,
+ 'endPos': 449,
'compiled': true,
'coverage': {
'hits': [],
- 'misses': [397]
+ 'misses': [399]
}
},
reportLines: false,
@@ -82,12 +84,12 @@
coverageTest(
{
'scriptIndex': 0,
- 'startPos': 397,
- 'endPos': 447,
+ 'startPos': 399,
+ 'endPos': 449,
'compiled': true,
'coverage': {
'hits': [],
- 'misses': [11]
+ 'misses': [13]
}
},
reportLines: true,
@@ -97,11 +99,11 @@
coverageTest(
{
'scriptIndex': 0,
- 'startPos': 397,
- 'endPos': 447,
+ 'startPos': 399,
+ 'endPos': 449,
'compiled': true,
'coverage': {
- 'hits': [397],
+ 'hits': [399],
'misses': []
}
},
@@ -110,11 +112,11 @@
coverageTest(
{
'scriptIndex': 0,
- 'startPos': 397,
- 'endPos': 447,
+ 'startPos': 399,
+ 'endPos': 449,
'compiled': true,
'coverage': {
- 'hits': [11],
+ 'hits': [13],
'misses': []
}
},
diff --git a/pkg/vm_service/test/coverage_optimized_function_test.dart b/pkg/vm_service/test/coverage_optimized_function_test.dart
new file mode 100644
index 0000000..129fddc7
--- /dev/null
+++ b/pkg/vm_service/test/coverage_optimized_function_test.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2017, 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.
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10
+
+import 'dart:developer';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+String optimizedFunction() {
+ return 5.toString() + 3.toString();
+}
+
+void testFunction() {
+ for (var i = 0; i < 20; i++) {
+ optimizedFunction();
+ }
+ debugger();
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+ final stack = await service.getStack(isolateId);
+
+ // Make sure we are in the right place.
+ expect(stack.frames!.length, greaterThanOrEqualTo(1));
+ expect(stack.frames![0].function!.name, 'testFunction');
+
+ final root =
+ await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+ final func = await service.getObject(
+ isolateId,
+ root.functions!.singleWhere((f) => f.name == 'optimizedFunction').id!,
+ ) as Func;
+
+ final report = await service.getSourceReport(
+ isolateId,
+ ['Coverage'],
+ scriptId: func.location!.script!.id!,
+ tokenPos: func.location!.tokenPos,
+ endTokenPos: func.location!.endTokenPos,
+ forceCompile: true,
+ );
+ expect(report.ranges!.length, 1);
+ final range = report.ranges![0];
+ expect(range.scriptIndex, 0);
+ expect(range.startPos, 476);
+ expect(range.endPos, 543);
+ expect(range.compiled, true);
+ final coverage = range.coverage!;
+ expect(coverage.hits, const [476, 516, 527, 531]);
+ expect(coverage.misses, isEmpty);
+ expect(report.scripts!.length, 1);
+ expect(
+ report.scripts![0].uri,
+ endsWith('coverage_optimized_function_test.dart'),
+ );
+ },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+ args,
+ tests,
+ 'coverage_optimized_function_test.dart',
+ testeeConcurrent: testFunction,
+ );
diff --git a/pkg/vm_service/test/debugger_inspect_test.dart b/pkg/vm_service/test/debugger_inspect_test.dart
new file mode 100644
index 0000000..ab85371
--- /dev/null
+++ b/pkg/vm_service/test/debugger_inspect_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+class Point {
+ int x, y;
+ Point(this.x, this.y);
+}
+
+void testeeDo() {
+ inspect(Point(3, 4));
+}
+
+final tests = <IsolateTest>[
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+
+ final completer = Completer();
+ late StreamSubscription sub;
+ sub = service.onDebugEvent.listen((event) async {
+ if (event.kind == EventKind.kInspect) {
+ expect(event.inspectee!.classRef!.name, 'Point');
+ await sub.cancel();
+ await service.streamCancel(EventStreams.kDebug);
+ completer.complete();
+ }
+ });
+
+ await service.streamListen(EventStreams.kDebug);
+
+ // Start listening for events first.
+ await service.evaluate(
+ isolateRef.id!,
+ isolate.rootLib!.id!,
+ 'testeeDo()',
+ );
+ await completer.future;
+ },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+ args,
+ tests,
+ 'debugger_inspect_test.dart',
+ );
diff --git a/pkg/vm_service/test/debugging_inlined_finally_test.dart b/pkg/vm_service/test/debugging_inlined_finally_test.dart
new file mode 100644
index 0000000..c6ebeda
--- /dev/null
+++ b/pkg/vm_service/test/debugging_inlined_finally_test.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const int LINE_A = 25;
+const int LINE_B = 28;
+const int LINE_C = 31;
+
+testFunction() {
+ debugger();
+ var a;
+ try {
+ var b;
+ try {
+ for (int i = 0; i < 10; i++) {
+ var x = () => i + a + b;
+ return x; // LINE_A
+ }
+ } finally {
+ b = 10; // LINE_B
+ }
+ } finally {
+ a = 1; // LINE_C
+ }
+}
+
+testMain() {
+ var f = testFunction();
+ expect(f(), equals(11));
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ // Add breakpoint
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ Isolate isolate = await service.getIsolate(isolateId);
+ final rootLib =
+ await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+
+ final script =
+ await service.getObject(isolateId, rootLib.scripts![0].id!) as Script;
+
+ // Add 3 breakpoints.
+ {
+ final bpt = await service.addBreakpoint(isolateId, script.id!, LINE_A);
+ expect(bpt.location!.script.id!, script.id);
+ final tmpScript =
+ await service.getObject(isolateId, script.id!) as Script;
+ expect(
+ tmpScript.getLineNumberFromTokenPos(bpt.location!.tokenPos),
+ LINE_A,
+ );
+ isolate = await service.getIsolate(isolateId);
+ expect(isolate.breakpoints!.length, 1);
+ }
+
+ {
+ final bpt = await service.addBreakpoint(isolateId, script.id!, LINE_B);
+ expect(bpt.location!.script.id, script.id);
+ final tmpScript =
+ await service.getObject(isolateId, script.id!) as Script;
+ expect(
+ tmpScript.getLineNumberFromTokenPos(bpt.location!.tokenPos),
+ LINE_B,
+ );
+ isolate = await service.getIsolate(isolateId);
+ expect(isolate.breakpoints!.length, 2);
+ }
+
+ {
+ final bpt = await service.addBreakpoint(isolateId, script.id!, LINE_C);
+ expect(bpt.location!.script.id, script.id!);
+ final tmpScript =
+ await service.getObject(isolateId, script.id!) as Script;
+ expect(
+ tmpScript.getLineNumberFromTokenPos(bpt.location!.tokenPos),
+ LINE_C,
+ );
+ isolate = await service.getIsolate(isolateId);
+ expect(isolate.breakpoints!.length, 3);
+ }
+ // Wait for breakpoint events.
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ // We are at the breakpoint on line LINE_A.
+ (VmService service, IsolateRef isolateRef) async {
+ final stack = await service.getStack(isolateRef.id!);
+ expect(stack.frames!.length, greaterThanOrEqualTo(1));
+
+ final script = await service.getObject(
+ isolateRef.id!, stack.frames![0].location!.script!.id!) as Script;
+ expect(
+ script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
+ LINE_A,
+ );
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ // We are at the breakpoint on line LINE_B.
+ (VmService service, IsolateRef isolateRef) async {
+ final stack = await service.getStack(isolateRef.id!);
+ expect(stack.frames!.length, greaterThanOrEqualTo(1));
+
+ final script = await service.getObject(
+ isolateRef.id!, stack.frames![0].location!.script!.id!) as Script;
+ expect(
+ script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
+ LINE_B,
+ );
+ },
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ // We are at the breakpoint on line LINE_C.
+ (VmService service, IsolateRef isolateRef) async {
+ final stack = await service.getStack(isolateRef.id!);
+ expect(stack.frames!.length, greaterThanOrEqualTo(1));
+
+ final script = await service.getObject(
+ isolateRef.id!, stack.frames![0].location!.script!.id!) as Script;
+ expect(
+ script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
+ LINE_C,
+ );
+ },
+ resumeIsolate,
+];
+
+main(args) => runIsolateTests(
+ args,
+ tests,
+ 'debugging_inlined_finally_test.dart',
+ testeeConcurrent: testMain,
+ );
diff --git a/pkg/vm_service/test/developer_extension_test.dart b/pkg/vm_service/test/developer_extension_test.dart
new file mode 100644
index 0000000..baa5115
--- /dev/null
+++ b/pkg/vm_service/test/developer_extension_test.dart
@@ -0,0 +1,137 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+// ignore: import_of_legacy_library_into_null_safe
+import 'package:expect/expect.dart';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+Future<ServiceExtensionResponse> Handler(String method, Map paremeters) {
+ print('Invoked extension: $method');
+ switch (method) {
+ case 'ext..delay':
+ var c = Completer<ServiceExtensionResponse>();
+ Timer(Duration(seconds: 1), () {
+ c.complete(ServiceExtensionResponse.result(jsonEncode({
+ 'type': '_delayedType',
+ 'method': method,
+ 'parameters': paremeters,
+ })));
+ });
+ return c.future;
+ case 'ext..error':
+ return Future<ServiceExtensionResponse>.value(
+ ServiceExtensionResponse.error(
+ ServiceExtensionResponse.extensionErrorMin, 'My error detail.'));
+ case 'ext..exception':
+ throw "I always throw!";
+ case 'ext..success':
+ return Future<ServiceExtensionResponse>.value(
+ ServiceExtensionResponse.result(jsonEncode({
+ 'type': '_extensionType',
+ 'method': method,
+ 'parameters': paremeters,
+ })));
+ }
+ throw "Unknown extension: $method";
+}
+
+void test() {
+ registerExtension('ext..delay', Handler);
+ debugger();
+ postEvent('ALPHA', {'cat': 'dog'});
+ debugger();
+ registerExtension('ext..error', Handler);
+ registerExtension('ext..exception', Handler);
+ registerExtension('ext..success', Handler);
+ bool exceptionThrown = false;
+ try {
+ registerExtension('ext..delay', Handler);
+ } catch (e) {
+ exceptionThrown = true;
+ }
+ // This check is running in the target process so we can't used package:test.
+ Expect.equals(exceptionThrown, true);
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ (VmService service, IsolateRef isolateRef) async {
+ final isolate = await service.getIsolate(isolateRef.id!);
+ // Note: extensions other than those is this test might already be
+ // registered by core libraries.
+ expect(isolate.extensionRPCs, contains('ext..delay'));
+ expect(isolate.extensionRPCs, isNot(contains('ext..error')));
+ expect(isolate.extensionRPCs, isNot(contains('ext..exception')));
+ expect(isolate.extensionRPCs, isNot(contains('ext..success')));
+ },
+ resumeIsolateAndAwaitEvent(EventStreams.kExtension, (event) {
+ expect(event.kind, EventKind.kExtension);
+ expect(event.extensionKind, 'ALPHA');
+ expect(event.extensionData!.data['cat'], equals('dog'));
+ }),
+ hasStoppedAtBreakpoint,
+ resumeIsolateAndAwaitEvent(EventStreams.kIsolate, (event) {
+ // Check that we received an event when '__error' was registered.
+ expect(event.kind, equals(EventKind.kServiceExtensionAdded));
+ expect(event.extensionRPC, 'ext..error');
+ }),
+ // Initial.
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ var result = await service.callServiceExtension(
+ 'ext..delay',
+ isolateId: isolateId,
+ );
+
+ expect(result.json!['type'], '_delayedType');
+ expect(result.json!['method'], equals('ext..delay'));
+ expect(result.json!['parameters']['isolateId'], isNotNull);
+
+ try {
+ await service.callServiceExtension(
+ 'ext..error',
+ isolateId: isolateId,
+ );
+ } on RPCError catch (e) {
+ expect(e.code, ServiceExtensionResponse.extensionErrorMin);
+ expect(e.details, 'My error detail.');
+ }
+
+ try {
+ await service.callServiceExtension(
+ 'ext..exception',
+ isolateId: isolateId,
+ );
+ } on RPCError catch (e) {
+ expect(e.code, ServiceExtensionResponse.extensionError);
+ expect(e.details!.startsWith('I always throw!\n'), isTrue);
+ }
+
+ result = await service.callServiceExtension(
+ 'ext..success',
+ isolateId: isolateId,
+ args: {
+ 'apple': 'banana',
+ },
+ );
+ expect(result.json!['type'], '_extensionType');
+ expect(result.json!['method'], 'ext..success');
+ expect(result.json!['parameters']['isolateId'], isNotNull);
+ expect(result.json!['parameters']['apple'], 'banana');
+ },
+];
+
+main([args = const <String>[]]) async => runIsolateTests(
+ args,
+ tests,
+ 'developer_extension_test.dart',
+ testeeConcurrent: test,
+ );
diff --git a/pkg/vm_service/test/developer_service_get_isolate_id_test.dart b/pkg/vm_service/test/developer_service_get_isolate_id_test.dart
new file mode 100644
index 0000000..d60780c
--- /dev/null
+++ b/pkg/vm_service/test/developer_service_get_isolate_id_test.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'dart:isolate' as iso;
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+// testee state.
+late String selfId;
+late iso.Isolate childIsolate;
+late String childId;
+
+void spawnEntry(int i) {
+ debugger();
+}
+
+Future testeeMain() async {
+ debugger();
+ // Spawn an isolate.
+ childIsolate = await iso.Isolate.spawn(spawnEntry, 0);
+ // Assign the id for this isolate and it's child to strings so they can
+ // be read by the tester.
+ selfId = Service.getIsolateID(iso.Isolate.current)!;
+ childId = Service.getIsolateID(childIsolate)!;
+ debugger();
+}
+
+@pragma("vm:entry-point")
+getSelfId() => selfId;
+
+@pragma("vm:entry-point")
+getChildId() => childId;
+
+// tester state:
+late IsolateRef initialIsolate;
+late IsolateRef localChildIsolate;
+
+var tests = <VMTest>[
+ (VmService service) async {
+ final vm = await service.getVM();
+ // Sanity check.
+ expect(vm.isolates!.length, 1);
+ initialIsolate = vm.isolates![0];
+ await hasStoppedAtBreakpoint(service, initialIsolate);
+ // Resume.
+ await service.resume(initialIsolate.id!);
+ },
+ (VmService service) async {
+ // Initial isolate has paused at second debugger call.
+ await hasStoppedAtBreakpoint(service, initialIsolate);
+ },
+ (VmService service) async {
+ final vm = await service.getVM();
+
+ // Grab the child isolate.
+ localChildIsolate =
+ vm.isolates!.firstWhere((IsolateRef i) => i != initialIsolate);
+ expect(localChildIsolate, isNotNull);
+
+ // Reload the initial isolate.
+ initialIsolate = await service.getIsolate(initialIsolate.id!);
+
+ // Grab the root library.
+ Library rootLib = await service.getObject(
+ initialIsolate.id!,
+ (initialIsolate as Isolate).rootLib!.id!,
+ ) as Library;
+
+ // Grab self id.
+ final localSelfId = await service.invoke(
+ initialIsolate.id!,
+ rootLib.id!,
+ 'getSelfId',
+ [],
+ ) as InstanceRef;
+
+ // Check that the id reported from dart:loper matches the id reported
+ // from the service protocol.
+ expect(localSelfId.kind, InstanceKind.kString);
+ expect(initialIsolate.id, localSelfId.valueAsString);
+
+ // Grab the child isolate's id.
+ final localChildId =
+ await service.invoke(initialIsolate.id!, rootLib.id!, 'getChildId', [])
+ as InstanceRef;
+
+ // Check that the id reported from dart:loper matches the id reported
+ // from the service protocol.
+ expect(localChildId.kind, InstanceKind.kString);
+ expect(localChildIsolate.id, localChildId.valueAsString);
+ }
+];
+
+main(args) async => runVMTests(
+ args,
+ tests,
+ 'developer_service_get_isolate_id_test.dart',
+ testeeConcurrent: testeeMain,
+ );
diff --git a/pkg/vm_service/test/echo_test.dart b/pkg/vm_service/test/echo_test.dart
new file mode 100644
index 0000000..d21a524
--- /dev/null
+++ b/pkg/vm_service/test/echo_test.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:test/test.dart';
+import 'package:vm_service/src/vm_service.dart';
+import 'common/test_helper.dart';
+
+class EchoResponse extends Response {
+ static EchoResponse? parse(Map<String, dynamic>? json) =>
+ json == null ? null : EchoResponse._fromJson(json);
+
+ EchoResponse._fromJson(Map<String, dynamic> json) : text = json['text'];
+
+ @override
+ String get type => '_EchoResponse';
+ final String text;
+}
+
+var tests = <IsolateTest>[
+ (VmService service, IsolateRef isolateRef) async {
+ addTypeFactory('_EchoResponse', EchoResponse.parse);
+ },
+ (VmService service, IsolateRef isolateRef) async {
+ // Echo from VM target.
+ final result = await service.callMethod('_echo', args: {
+ 'text': 'hello',
+ });
+ expect(result, isA<EchoResponse>());
+ expect((result as EchoResponse).text, 'hello');
+ },
+ (VmService service, IsolateRef isolateRef) async {
+ // Echo from Isolate target.
+ final result =
+ await service.callMethod('_echo', isolateId: isolateRef.id!, args: {
+ 'text': 'hello',
+ });
+ expect(result, isA<EchoResponse>());
+ expect((result as EchoResponse).text, 'hello');
+ },
+ (VmService service, IsolateRef isolateRef) async {
+ final completer = Completer<void>();
+ late final StreamSubscription sub;
+ sub = service.onEvent('_Echo').listen((event) async {
+ expect(event.kind, '_Echo');
+ expect(event.data!.lengthInBytes, 3);
+ expect(event.data!.getUint8(0), 0);
+ expect(event.data!.getUint8(1), 128);
+ expect(event.data!.getUint8(2), 255);
+ await sub.cancel();
+ await service.streamCancel('_Echo');
+ completer.complete();
+ });
+
+ await service.streamListen('_Echo');
+ await service.callMethod(
+ '_triggerEchoEvent',
+ isolateId: isolateRef.id!,
+ args: {
+ 'text': 'hello',
+ },
+ );
+ await completer.future;
+ },
+];
+
+main(args) => runIsolateTests(
+ args,
+ tests,
+ 'echo_test.dart',
+ );
diff --git a/pkg/vm_service/test/eval_internal_class_test.dart b/pkg/vm_service/test/eval_internal_class_test.dart
new file mode 100644
index 0000000..9ddeb00
--- /dev/null
+++ b/pkg/vm_service/test/eval_internal_class_test.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+var tests = <IsolateTest>[
+ (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+ final rootLib = await service.getObject(
+ isolateId,
+ isolate.rootLib!.id!,
+ ) as Library;
+ Class classLibrary = await service.getObject(
+ isolateId,
+ rootLib.classRef!.id!,
+ ) as Class;
+
+ {
+ bool caughtExceptions = false;
+ try {
+ dynamic result = await service.evaluate(
+ isolateId,
+ classLibrary.id!,
+ '3 + 4',
+ );
+ print(result);
+ } on RPCError catch (e) {
+ expect(e.toString(), contains('can be evaluated only'));
+ caughtExceptions = true;
+ }
+ expect(caughtExceptions, isTrue);
+ }
+
+ final classClass = await service.getObject(
+ isolateId,
+ classLibrary.classRef!.id!,
+ ) as Class;
+ {
+ bool caughtExceptions = false;
+ try {
+ dynamic result = await service.evaluate(
+ isolateId,
+ classClass.id!,
+ '3 + 4',
+ );
+ print(result);
+ } on RPCError catch (e) {
+ expect(e.toString(), contains('can be evaluated only'));
+ caughtExceptions = true;
+ }
+ expect(caughtExceptions, isTrue);
+ }
+ final classArray = await service.getObject(
+ isolateId,
+ (await service.evaluate(
+ isolateId,
+ rootLib.id!,
+ "List<dynamic>.filled(2, null)",
+ ) as InstanceRef)
+ .classRef!
+ .id!,
+ ) as Class;
+ dynamic result = await service.evaluate(
+ isolateId,
+ classArray.id!,
+ '3 + 4',
+ );
+ expect(result is InstanceRef, isTrue);
+ expect(result.valueAsString, '7');
+ },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+ args,
+ tests,
+ 'eval_internal_class_test.dart',
+ );
diff --git a/pkg/vm_service/test/eval_regression_flutter20255_test.dart b/pkg/vm_service/test/eval_regression_flutter20255_test.dart
new file mode 100644
index 0000000..6d3b963
--- /dev/null
+++ b/pkg/vm_service/test/eval_regression_flutter20255_test.dart
@@ -0,0 +1,108 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+class Base<T> {
+ String field;
+
+ Base(this.field);
+ String foo() => 'Base-$field';
+}
+
+class Sub<T> extends Base<T> {
+ String field;
+
+ Sub(this.field) : super(field);
+ String foo() {
+ debugger();
+ return 'Sub-$field';
+ }
+}
+
+class ISub<T> implements Base<T> {
+ String field;
+
+ ISub(this.field);
+ String foo() => 'ISub-$field';
+}
+
+class Box<T> {
+ late T value;
+
+ @pragma('vm:never-inline')
+ void setValue(T value) {
+ this.value = value;
+ }
+}
+
+final objects = <Base>[Base<int>('b'), Sub<double>('a'), ISub<bool>('c')];
+
+String triggerTypeTestingStubGeneration() {
+ final Box<Object> box = Box<Base>();
+ for (int i = 0; i < 1000000; ++i) {
+ box.setValue(objects.last);
+ }
+ return 'tts-generated';
+}
+
+void testFunction() {
+ // Triggers the debugger, which will evaluate an expression in the context of
+ // [Sub<double>], which will make a subclass of [Base<T>].
+ print(objects[1].foo());
+
+ triggerTypeTestingStubGeneration();
+
+ // Triggers the debugger, which will evaluate an expression in the context of
+ // [Sub<double>], which will make a subclass of [Base<T>].
+ print(objects[1].foo());
+}
+
+Future triggerEvaluation(VmService service, IsolateRef isolateRef) async {
+ Stack stack = await service.getStack(isolateRef.id!);
+
+ // Make sure we are in the right place.
+ expect(stack.frames!.length, greaterThanOrEqualTo(2));
+ expect(stack.frames![0].function!.name, 'foo');
+ expect(stack.frames![0].function!.owner.name, 'Sub');
+
+ // Trigger an evaluation, which will create a subclass of Base<T>.
+ final dynamic result = await service.evaluateInFrame(
+ isolateRef.id!,
+ 0,
+ 'this.field + " world \$T"',
+ );
+ expect(result.valueAsString, 'a world double');
+
+ // Trigger an optimization of a type testing stub (and usage of it).
+ final dynamic result2 = await service.evaluateInFrame(
+ isolateRef.id!,
+ 0,
+ 'triggerTypeTestingStubGeneration()',
+ );
+ expect(result2.valueAsString, 'tts-generated');
+}
+
+final testSteps = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ triggerEvaluation,
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ triggerEvaluation,
+ resumeIsolate,
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+ args,
+ testSteps,
+ 'eval_regression_flutter20255_test.dart',
+ testeeConcurrent: testFunction,
+ );
diff --git a/pkg/vm_service/test/eval_skip_breakpoint.dart b/pkg/vm_service/test/eval_skip_breakpoint.dart
new file mode 100644
index 0000000..cdb4d5c
--- /dev/null
+++ b/pkg/vm_service/test/eval_skip_breakpoint.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, 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.
+// VMOptions=--verbose_debug
+
+import 'dart:developer';
+
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const int LINE_A = 22;
+const int LINE_B = 17;
+
+bar() {
+ print('bar');
+}
+
+testMain() {
+ debugger();
+ bar();
+ print("Done");
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_A),
+ // Add breakpoint
+ setBreakpointAtLine(LINE_B),
+ // Evaluate 'bar()'
+ (VmService service, IsolateRef isolateRef) async {
+ final isolate = await service.getIsolate(isolateRef.id!);
+ await service.evaluate(
+ isolateRef.id!,
+ isolate.rootLib!.id!,
+ 'bar()',
+ disableBreakpoints: true,
+ );
+ },
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_A),
+ resumeIsolate,
+
+ hasStoppedAtBreakpoint,
+ stoppedAtLine(LINE_B),
+ resumeIsolate,
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+ args,
+ tests,
+ 'eval_skip_breakpoint.dart',
+ testeeConcurrent: testMain,
+ );
diff --git a/pkg/vm_service/test/evaluate_activation_in_method_class_other.dart b/pkg/vm_service/test/evaluate_activation_in_method_class_other.dart
new file mode 100644
index 0000000..000ba5e
--- /dev/null
+++ b/pkg/vm_service/test/evaluate_activation_in_method_class_other.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+
+var topLevel = "OtherLibrary";
+
+class Superclass2 {
+ var _instVar = 'Superclass2';
+ var instVar = 'Superclass2';
+ method() => 'Superclass2';
+ static staticMethod() => 'Superclass2';
+ suppress_warning() => _instVar;
+}
+
+class Superclass1 extends Superclass2 {
+ var _instVar = 'Superclass1';
+ var instVar = 'Superclass1';
+ method() => 'Superclass1';
+ static staticMethod() => 'Superclass1';
+
+ test() {
+ var _local = 'Superclass1';
+ debugger();
+ // Suppress unused variable warning.
+ print(_local);
+ }
+}
diff --git a/pkg/vm_service/test/evaluate_activation_in_method_class_test.dart b/pkg/vm_service/test/evaluate_activation_in_method_class_test.dart
new file mode 100644
index 0000000..0e1cc1d
--- /dev/null
+++ b/pkg/vm_service/test/evaluate_activation_in_method_class_test.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2016, 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.
+
+// Tests that expressions evaluated in a frame see the same scope as the
+// frame's method.
+
+import 'dart:async';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+import 'evaluate_activation_in_method_class_other.dart';
+
+var topLevel = "TestLibrary";
+
+class Subclass extends Superclass1 {
+ var _instVar = 'Subclass';
+ var instVar = 'Subclass';
+ method() => 'Subclass';
+ static staticMethod() => 'Subclass';
+ suppress_warning() => _instVar;
+}
+
+testeeDo() {
+ var obj = Subclass();
+ obj.test();
+}
+
+Future testerDo(VmService service, IsolateRef isolateRef) async {
+ await hasStoppedAtBreakpoint(service, isolateRef);
+ final isolateId = isolateRef.id!;
+
+ // Make sure we are in the right place.
+ var stack = await service.getStack(isolateId);
+ var topFrame = 0;
+ expect(
+ stack.frames![topFrame].function!.name,
+ equals('test'),
+ );
+ expect(
+ stack.frames![topFrame].function!.owner.name,
+ equals('Superclass1'),
+ );
+
+ InstanceRef result;
+
+ result = await service.evaluateInFrame(isolateId, topFrame, '_local')
+ as InstanceRef;
+ print(result);
+ expect(result.valueAsString, equals('Superclass1'));
+
+ result = await service.evaluateInFrame(isolateId, topFrame, '_instVar')
+ as InstanceRef;
+ print(result);
+ expect(result.valueAsString, equals('Superclass1'));
+
+ result = await service.evaluateInFrame(isolateId, topFrame, 'instVar')
+ as InstanceRef;
+ print(result);
+ expect(result.valueAsString, equals('Subclass'));
+
+ result = await service.evaluateInFrame(isolateId, topFrame, 'method()')
+ as InstanceRef;
+ print(result);
+ expect(result.valueAsString, equals('Subclass'));
+
+ result = await service.evaluateInFrame(isolateId, topFrame, 'super._instVar')
+ as InstanceRef;
+ print(result);
+ expect(result.valueAsString, equals('Superclass2'));
+
+ result = await service.evaluateInFrame(isolateId, topFrame, 'super.instVar')
+ as InstanceRef;
+ print(result);
+ expect(result.valueAsString, equals('Superclass2'));
+
+ result = await service.evaluateInFrame(isolateId, topFrame, 'super.method()')
+ as InstanceRef;
+ print(result);
+ expect(result.valueAsString, equals('Superclass2'));
+
+ result = await service.evaluateInFrame(isolateId, topFrame, 'staticMethod()')
+ as InstanceRef;
+ print(result);
+ expect(result.valueAsString, equals('Superclass1'));
+
+ // function.Owner verus function.Origin
+ // The mixin of Superclass is in _other.dart and the mixin
+ // application is in _test.dart.
+ result = await service.evaluateInFrame(isolateId, topFrame, 'topLevel')
+ as InstanceRef;
+ print(result);
+ expect(result.valueAsString, equals('OtherLibrary'));
+}
+
+main([args = const <String>[]]) => runIsolateTests(
+ args,
+ [testerDo],
+ 'evaluate_activation_in_method_class_test.dart',
+ testeeConcurrent: testeeDo,
+ );
diff --git a/pkg/vm_service/tool/java/generate_java.dart b/pkg/vm_service/tool/java/generate_java.dart
index c80a481..0f61371 100644
--- a/pkg/vm_service/tool/java/generate_java.dart
+++ b/pkg/vm_service/tool/java/generate_java.dart
@@ -259,11 +259,14 @@
String? h3Name;
+ // TODO(helin24): This code does not capture documentation with more than
+ // one paragraph or lists. It may help to check generate_dart to fix this.
for (int i = 0; i < nodes.length; i++) {
Node node = nodes[i];
if (isPre(node) && h3Name != null) {
- String definition = textForCode(node);
+ String definition = textForCode(node)
+ .replaceAll('(string|Null)', 'string'); // this is terrible.
String? docs;
if (i + 1 < nodes.length && isPara(nodes[i + 1])) {
@@ -638,7 +641,8 @@
}
/// TODO: Hacked enum arg type determination
- bool get isEnumType => name == 'step' || name == 'mode';
+ bool get isEnumType =>
+ name == 'step' || name == 'mode' || name == 'exceptionPauseMode';
}
class MethodParser extends Parser {
diff --git a/pkg/vm_service/tool/java/version.properties b/pkg/vm_service/tool/java/version.properties
new file mode 100644
index 0000000..1c8ad22
--- /dev/null
+++ b/pkg/vm_service/tool/java/version.properties
@@ -0,0 +1 @@
+version=3.56
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index cb64707..0e97fbb 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -888,7 +888,9 @@
ASSERT(!function_.IsNull());
auto isolate_group = IsolateGroup::Current();
if (function_.ptr() ==
- isolate_group->object_store()->complete_on_async_return()) {
+ isolate_group->object_store()->complete_on_async_return() ||
+ function_.ptr() == isolate_group->object_store()
+ ->complete_with_no_future_on_async_return()) {
// We are completing an async function's completer.
return true;
}
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 8ce45e3..81c5977 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -210,6 +210,15 @@
return result.ptr();
}
+#if !defined(DART_PRECOMPILED_RUNTIME)
+static void DisableDebuggingAndInlining(const Function& function) {
+ if (FLAG_async_debugger) {
+ function.set_is_debuggable(false);
+ function.set_is_inlinable(false);
+ }
+}
+#endif // DART_PRECOMPILED_RUNTIME
+
void ObjectStore::InitKnownObjects() {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
@@ -251,11 +260,16 @@
function_name, 0, 3, Object::null_array());
ASSERT(!function.IsNull());
set_complete_on_async_return(function);
- if (FLAG_async_debugger) {
- // Disable debugging and inlining the _CompleteOnAsyncReturn function.
- function.set_is_debuggable(false);
- function.set_is_inlinable(false);
- }
+ DisableDebuggingAndInlining(function);
+
+ function_name =
+ async_lib.PrivateName(Symbols::_CompleteWithNoFutureOnAsyncReturn());
+ ASSERT(!function_name.IsNull());
+ function = Resolver::ResolveStatic(async_lib, Object::null_string(),
+ function_name, 0, 3, Object::null_array());
+ ASSERT(!function.IsNull());
+ set_complete_with_no_future_on_async_return(function);
+ DisableDebuggingAndInlining(function);
function_name = async_lib.PrivateName(Symbols::_CompleteOnAsyncError());
ASSERT(!function_name.IsNull());
@@ -263,11 +277,7 @@
function_name, 0, 4, Object::null_array());
ASSERT(!function.IsNull());
set_complete_on_async_error(function);
- if (FLAG_async_debugger) {
- // Disable debugging and inlining the _CompleteOnAsyncError function.
- function.set_is_debuggable(false);
- function.set_is_inlinable(false);
- }
+ DisableDebuggingAndInlining(function);
cls =
async_lib.LookupClassAllowPrivate(Symbols::_AsyncStarStreamController());
@@ -283,8 +293,7 @@
if (function.IsNull()) {
break;
}
- function.set_is_debuggable(false);
- function.set_is_inlinable(false);
+ DisableDebuggingAndInlining(function);
}
}
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 3d77c61..896c01b 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -159,6 +159,7 @@
RW(Function, simple_instance_of_false_function) \
RW(Function, async_star_move_next_helper) \
RW(Function, complete_on_async_return) \
+ RW(Function, complete_with_no_future_on_async_return) \
RW(Function, complete_on_async_error) \
RW(Class, async_star_stream_controller) \
ARW_RELAXED(Smi, future_timeout_future_index) \
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index ed6e095..368f70b 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1903,7 +1903,7 @@
_@Code_ is a reference to a _Code_ object.
```
-class Code extends @Object {
+class Code extends Object {
// A name for this code object.
string name;
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 5c8db08..6c9758a 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -288,6 +288,7 @@
V(_CombinatorMirror, "_CombinatorMirror") \
V(_CompileTimeError, "_CompileTimeError") \
V(_CompleteOnAsyncReturn, "_completeOnAsyncReturn") \
+ V(_CompleteWithNoFutureOnAsyncReturn, "_completeWithNoFutureOnAsyncReturn") \
V(_ControllerSubscription, "_ControllerSubscription") \
V(_CompleteOnAsyncError, "_completeOnAsyncError") \
V(_DeletedEnumPrefix, "Deleted enum value from ") \
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
index f4ab556..ca3bd4f 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
@@ -62,3 +62,6 @@
@patch
bool isSentinel(dynamic value) => throw UnsupportedError('isSentinel');
+
+@patch
+T unsafeCast<T>(dynamic v) => v;
diff --git a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
index 9bf6da6..ef27959 100644
--- a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
@@ -73,3 +73,7 @@
@patch
@pragma('dart2js:tryInline')
bool isSentinel(dynamic value) => isJsSentinel(value);
+
+@patch
+@pragma('dart2js:tryInline')
+T unsafeCast<T>(dynamic v) => v;
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index 363ae71..ee371e7 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -257,7 +257,20 @@
// allow then and error handlers to be attached.
// async_jump_var=0 is prior to first await, =1 is first await.
if (!is_sync || value is Future) {
- _future._asyncComplete(value);
+ _future._asyncCompleteUnchecked(value);
+ } else {
+ _future._completeWithValue(value);
+ }
+}
+
+@pragma("vm:entry-point", "call")
+void _completeWithNoFutureOnAsyncReturn(
+ _Future _future, Object? value, bool is_sync) {
+ // The first awaited expression is invoked sync. so complete is async. to
+ // allow then and error handlers to be attached.
+ // async_jump_var=0 is prior to first await, =1 is first await.
+ if (!is_sync) {
+ _future._asyncCompleteUncheckedNoFuture(value);
} else {
_future._completeWithValue(value);
}
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index b8141d6..3d7a3cd8f 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -156,13 +156,9 @@
return newStack;
}
-// This function can be used to skip implicit or explicit checked down casts in
-// the parts of the core library implementation where we know by construction the
-// type of a value.
-//
-// Important: this is unsafe and must be used with care.
+@patch
@pragma("vm:external-name", "Internal_unsafeCast")
-external T unsafeCast<T>(Object? v);
+external T unsafeCast<T>(dynamic v);
// This function can be used to keep an object alive till that point.
@pragma("vm:recognized", "other")
diff --git a/sdk/lib/_internal/vm/lib/timer_impl.dart b/sdk/lib/_internal/vm/lib/timer_impl.dart
index ac1939d..32f43d0 100644
--- a/sdk/lib/_internal/vm/lib/timer_impl.dart
+++ b/sdk/lib/_internal/vm/lib/timer_impl.dart
@@ -452,8 +452,9 @@
if (_receivePort == null) {
assert(_receivePort == null);
assert(_sendPort == null);
- _receivePort = RawReceivePort(_handleMessage, 'Timer');
- _sendPort = _receivePort!.sendPort;
+ final port = RawReceivePort(_handleMessage, 'Timer');
+ _receivePort = port;
+ _sendPort = port.sendPort;
_scheduledWakeupTime = 0;
} else {
(_receivePort as _RawReceivePortImpl)._setActive(true);
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index 0b16dae..ca05fc6 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -114,7 +114,8 @@
printToZone,
printToConsole,
Since,
- typeAcceptsNull;
+ typeAcceptsNull,
+ unsafeCast;
part 'async_error.dart';
part 'broadcast_stream_controller.dart';
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 4d13cc8..1b7176e 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -4,15 +4,6 @@
part of dart.async;
-/// The onValue and onError handlers return either a value or a future
-typedef FutureOr<T> _FutureOnValue<S, T>(S value);
-
-/// Test used by [Future.catchError] to handle skip some errors.
-typedef bool _FutureErrorTest(Object error);
-
-/// Used by [WhenFuture].
-typedef dynamic _FutureAction();
-
abstract class _Completer<T> implements Completer<T> {
final _Future<T> future = new _Future<T>();
@@ -106,7 +97,7 @@
state = (errorCallback == null) ? stateThen : stateThenOnerror;
_FutureListener.thenAwait(
- this.result, _FutureOnValue<S, T> onValue, Function errorCallback)
+ this.result, FutureOr<T> Function(S) onValue, Function errorCallback)
: callback = onValue,
errorCallback = errorCallback,
state = stateThenOnerror;
@@ -127,19 +118,19 @@
FutureOr<T> Function(S) get _onValue {
assert(handlesValue);
- return callback as dynamic;
+ return unsafeCast<FutureOr<T> Function(S)>(callback);
}
Function? get _onError => errorCallback;
- _FutureErrorTest get _errorTest {
+ bool Function(Object) get _errorTest {
assert(hasErrorTest);
- return callback as dynamic;
+ return unsafeCast<bool Function(Object)>(callback);
}
- _FutureAction get _whenCompleteAction {
+ dynamic Function() get _whenCompleteAction {
assert(handlesComplete);
- return callback as dynamic;
+ return unsafeCast<dynamic Function()>(callback);
}
/// Whether this listener has an error callback.
@@ -607,6 +598,37 @@
_asyncCompleteWithValue(value as dynamic); // Value promoted to T.
}
+ /// Internal helper function used by the implementation of `async` functions.
+ ///
+ /// Like [_asyncComplete], but avoids type checks that are guaranteed to
+ /// succeed by the way the function is called.
+ /// Should be used judiciously.
+ void _asyncCompleteUnchecked(/*FutureOr<T>*/ dynamic value) {
+ assert((value as FutureOr<T>) == value);
+ final typedValue = unsafeCast<FutureOr<T>>(value);
+
+ // Doing just "is Future" is not sufficient.
+ // If `T` is Object` and `value` is `Future<Object?>.value(null)`,
+ // then value is a `Future`, but not a `Future<T>`, and going through the
+ // `_chainFuture` branch would end up assigning `null` to `Object`.
+ if (typedValue is Future<T>) {
+ _chainFuture(typedValue);
+ return;
+ }
+ _asyncCompleteWithValue(unsafeCast<T>(typedValue));
+ }
+
+ /// Internal helper function used to implement `async` functions.
+ ///
+ /// Like [_asyncCompleteUnchecked], but avoids a `is Future<T>` check due to
+ /// having a static guarantee on the callsite that the [value] cannot be a
+ /// [Future].
+ /// Should be used judiciously.
+ void _asyncCompleteUncheckedNoFuture(/*T*/ dynamic value) {
+ assert((value as T) == value);
+ _asyncCompleteWithValue(unsafeCast<T>(value));
+ }
+
void _asyncCompleteWithValue(T value) {
_setPendingComplete();
_zone.scheduleMicrotask(() {
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index 9a7afe2..968c555 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -18,6 +18,7 @@
part 'abi.dart';
part 'abi_specific.dart';
part 'native_type.dart';
+part 'native_finalizer.dart';
part 'allocation.dart';
part 'annotations.dart';
part 'c_type.dart';
diff --git a/sdk/lib/ffi/ffi_sources.gni b/sdk/lib/ffi/ffi_sources.gni
index 4197369..c530899 100644
--- a/sdk/lib/ffi/ffi_sources.gni
+++ b/sdk/lib/ffi/ffi_sources.gni
@@ -12,6 +12,7 @@
"annotations.dart",
"c_type.dart",
"dynamic_library.dart",
+ "native_finalizer.dart",
"native_type.dart",
"struct.dart",
"union.dart",
diff --git a/sdk/lib/ffi/native_finalizer.dart b/sdk/lib/ffi/native_finalizer.dart
new file mode 100644
index 0000000..49fc667
--- /dev/null
+++ b/sdk/lib/ffi/native_finalizer.dart
@@ -0,0 +1,223 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.ffi;
+
+/// Marker interface for objects which should not be finalized too soon.
+///
+/// Any local variable with a static type that _includes `Finalizable`_
+/// is guaranteed to be alive until execution exits the code block where
+/// the variable is in scope.
+///
+/// A type _includes `Finalizable`_ if either
+/// * the type is a non-`Never` subtype of `Finalizable`, or
+/// * the type is `T?` or `FutureOr<T>` where `T` includes `Finalizable`.
+///
+/// In other words, while an object is referenced by such a variable,
+/// it is guaranteed to *not* be considered unreachable,
+/// and the variable itself is considered alive for the entire duration
+/// of its scope, even after it is last referenced.
+///
+/// _Without this marker interface on the variable's type, a variable's
+/// value might be garbage collected before the surrounding scope has
+/// been completely executed, as long as the variable is definitely not
+/// referenced again. That can, in turn, trigger a `NativeFinalizer`
+/// to perform a callback. When the variable's type includes [Finalizable],
+/// The `NativeFinalizer` callback is prevented from running until
+/// the current code using that variable is complete._
+///
+/// For example, `finalizable` is kept alive during the execution of
+/// `someNativeCall`:
+///
+/// ```dart
+/// void myFunction() {
+/// final finalizable = MyFinalizable(Pointer.fromAddress(0));
+/// someNativeCall(finalizable.nativeResource);
+/// }
+///
+/// void someNativeCall(Pointer nativeResource) {
+/// // ..
+/// }
+///
+/// class MyFinalizable implements Finalizable {
+/// final Pointer nativeResource;
+///
+/// MyFinalizable(this.nativeResource);
+/// }
+/// ```
+///
+/// Methods on a class implementing `Finalizable` keep the `this` object alive
+/// for the duration of the method execution. _The `this` value is treated
+/// like a local variable._
+///
+/// For example, `this` is kept alive during the execution of `someNativeCall`
+/// in `myFunction`:
+///
+/// ```dart
+/// class MyFinalizable implements Finalizable {
+/// final Pointer nativeResource;
+///
+/// MyFinalizable(this.nativeResource);
+///
+/// void myFunction() {
+/// someNativeCall(nativeResource);
+/// }
+/// }
+///
+/// void someNativeCall(Pointer nativeResource) {
+/// // ..
+/// }
+/// ```
+///
+/// It is good practise to implement logic involving finalizables as methods
+/// on the class that implements [Finalizable].
+///
+/// If a closure is created inside the block scope declaring the variable, and
+/// that closure contains any reference to the variable, the variable stays
+/// alive as long as the closure object does, or as long as the body of such a
+/// closure is executing.
+///
+/// For example, `finalizable` is kept alive by the closure object and until the
+/// end of the closure body:
+///
+/// ```dart
+/// void doSomething() {
+/// final resourceAction = myFunction();
+/// resourceAction(); // `finalizable` is alive until this call returns.
+/// }
+///
+/// void Function() myFunction() {
+/// final finalizable = MyFinalizable(Pointer.fromAddress(0));
+/// return () {
+/// someNativeCall(finalizable.nativeResource);
+/// };
+/// }
+///
+/// void someNativeCall(Pointer nativeResource) {
+/// // ..
+/// }
+///
+/// class MyFinalizable implements Finalizable {
+/// final Pointer nativeResource;
+///
+/// MyFinalizable(this.nativeResource);
+/// }
+/// ```
+///
+/// Only captured variables are kept alive by closures, not all variables.
+///
+/// For example, `finalizable` is not kept alive by the returned closure object:
+///
+/// ```dart
+/// void Function() myFunction() {
+/// final finalizable = MyFinalizable(Pointer.fromAddress(0));
+/// final nativeResource = finalizable.nativeResource;
+/// return () {
+/// someNativeCall(nativeResource);
+/// };
+/// }
+///
+/// void someNativeCall(Pointer nativeResource) {
+/// // ..
+/// }
+///
+/// class MyFinalizable implements Finalizable {
+/// final Pointer nativeResource;
+///
+/// MyFinalizable(this.nativeResource);
+/// }
+/// ```
+///
+/// It's likely an error if a resource extracted from a finalizable object
+/// escapes the scope of the finalizable variable it's taken from.
+///
+/// The behavior of `Finalizable` variables applies to asynchronous
+/// functions too. Such variables are kept alive as long as any
+/// code may still execute inside the scope that declared the variable,
+/// or in a closure capturing the variable,
+/// even if there are asynchronous delays during that execution.
+///
+/// For example, `finalizable` is kept alive during the `await someAsyncCall()`:
+///
+/// ```dart
+/// Future<void> myFunction() async {
+/// final finalizable = MyFinalizable();
+/// await someAsyncCall();
+/// }
+///
+/// Future<void> someAsyncCall() async {
+/// // ..
+/// }
+///
+/// class MyFinalizable implements Finalizable {
+/// // ..
+/// }
+/// ```
+///
+/// Also in asynchronous code it's likely an error if a resource extracted from
+/// a finalizable object escapes the scope of the finalizable variable it's
+/// taken from. If you have to extract a resource from a `Finalizable`, you
+/// should ensure the scope in which Finalizable is defined outlives the
+/// resource by `await`ing any asynchronous code that uses the resource.
+///
+/// For example, `this` is kept alive until `resource` is not used anymore in
+/// `useAsync1`, but not in `useAsync2` and `useAsync3`:
+///
+/// ```dart
+/// class MyFinalizable {
+/// final Pointer<Int8> resource;
+///
+/// MyFinalizable(this.resource);
+///
+/// Future<int> useAsync1() async {
+/// return await useResource(resource);
+/// }
+///
+/// Future<int> useAsync2() async {
+/// return useResource(resource);
+/// }
+///
+/// Future<int> useAsync3() {
+/// return useResource(resource);
+/// }
+/// }
+///
+/// /// Does not use [resource] after the returned future completes.
+/// Future<int> useResource(Pointer<Int8> resource) async {
+/// return resource.value;
+/// }
+/// ```
+///
+/// _It is possible for an asynchronous function to *stall* at an
+/// `await`, such that the runtime system can see that there is no possible
+/// way for that `await` to complete. In that case, no code after the
+/// `await` will ever execute, including `finally` blocks, and the
+/// variable may be considered dead along with everything else._
+///
+/// If you're not going to keep a variable alive yourself, make sure to pass the
+/// finalizable object to other functions instead of just its resource.
+///
+/// For example, `finalizable` is not kept alive by `myFunction` after it has
+/// run to the end of its scope, while `someAsyncCall` could still continue
+/// execution. However, `finalizable` is kept alive by `someAsyncCall` itself:
+///
+/// ```dart
+/// void myFunction() {
+/// final finalizable = MyFinalizable();
+/// someAsyncCall(finalizable);
+/// }
+///
+/// Future<void> someAsyncCall(MyFinalizable finalizable) async {
+/// // ..
+/// }
+///
+/// class MyFinalizable implements Finalizable {
+/// // ..
+/// }
+/// ```
+// TODO(http://dartbug.com/44395): Add implicit await to Dart implementation.
+// This will fix `useAsync2` above.
+abstract class Finalizable {
+ factory Finalizable._() => throw UnsupportedError("");
+}
diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
index 5d38bd8..a7a7eda 100644
--- a/sdk/lib/internal/internal.dart
+++ b/sdk/lib/internal/internal.dart
@@ -35,6 +35,23 @@
// execution mode.
external bool typeAcceptsNull<T>();
+/// Unsafely treats [value] as type [T].
+///
+/// An unsafe cast allows casting any value to any type,
+/// without any runtime type checks.
+///
+/// Can be used internally in platform library implementations of
+/// data structures, where a value is known to have a type different
+/// from its static type (like knowing that a string is definitely
+/// a "_OneByteString" or that the value stored into a heterogenous
+/// list is really a value of the surrounding map).
+///
+/// Must only be used for casts which would definitely *succeed*
+/// as a normal cast.
+///
+/// Should only be used for performance in performance critical code.
+external T unsafeCast<T>(dynamic value);
+
// Powers of 10 up to 10^22 are representable as doubles.
// Powers of 10 above that are only approximate due to lack of precission.
// Used by double-parsing.
diff --git a/tools/VERSION b/tools/VERSION
index 8a18778..2811149 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 85
+PRERELEASE 86
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 740881b..f1dcf06 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -2264,17 +2264,6 @@
]
},
{
- "name": "ddc weak modular tests",
- "script": "out/ReleaseX64/dart-sdk/bin/dart",
- "testRunner": true,
- "arguments": [
- "pkg/dev_compiler/test/modular_suite_nnbd.dart",
- "-ndartdevk-weak-${system}-release-chrome",
- "--verbose",
- "--use-sdk"
- ]
- },
- {
"name": "ddc nnbd weak tests",
"arguments": [
"-ndartdevk-weak-linux-release-chrome",
@@ -2284,7 +2273,7 @@
"dartdevc",
"web"
],
- "shards": 5,
+ "shards": 2,
"fileset": "web_platform_nnbd"
},
{
@@ -2297,6 +2286,26 @@
"fileset": "web_platform_nnbd"
},
{
+ "name": "ddc nnbd strong co19 tests",
+ "arguments": [
+ "-ndartdevk-strong-linux-release-chrome",
+ "co19"
+ ],
+ "shards": 3,
+ "fileset": "web_platform_nnbd"
+ },
+ {
+ "name": "ddc weak modular tests",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
+ "testRunner": true,
+ "arguments": [
+ "pkg/dev_compiler/test/modular_suite_nnbd.dart",
+ "-ndartdevk-weak-${system}-release-chrome",
+ "--verbose",
+ "--use-sdk"
+ ]
+ },
+ {
"name": "ddc nnbd strong tests",
"arguments": [
"-ndartdevk-strong-linux-release-chrome",
@@ -2306,13 +2315,6 @@
"dartdevc",
"web"
]
- },
- {
- "name": "ddc nnbd strong co19 tests",
- "arguments": [
- "-ndartdevk-strong-linux-release-chrome",
- "co19"
- ]
}
]
},
@@ -4183,4 +4185,4 @@
"macos": "buildtools/mac-x64/clang/bin/llvm-symbolizer",
"windows": "buildtools/win-x64/clang/bin/llvm-symbolizer.exe"
}
-}
\ No newline at end of file
+}