[cfe] Handle default values on extension methods

Closes #38541

Change-Id: I078800cc98b5444c2c7f6f87b2d89bcf764bfc23
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118582
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
This commit is contained in:
Johnni Winther
2019-09-25 08:45:27 +00:00
committed by commit-bot@chromium.org
parent 1ffbebe07a
commit b03d472e4c
15 changed files with 305 additions and 37 deletions
@@ -6,6 +6,7 @@ library fasta.procedure_builder;
import 'dart:core' hide MapEntry;
import 'package:front_end/src/fasta/kernel/kernel_api.dart';
import 'package:kernel/ast.dart' hide Variance;
import 'package:kernel/type_algebra.dart';
@@ -361,6 +362,27 @@ abstract class FunctionBuilder extends MemberBuilder {
return function = result;
}
/// Returns the [index]th parameter of this function.
///
/// The index is the syntactical index, including both positional and named
/// parameter in the order they are declared, and excluding the synthesized
/// this parameter on extension instance members.
VariableDeclaration getFormalParameter(int index) {
if (isExtensionInstanceMember) {
return formals[index + 1].variable;
} else {
return formals[index].variable;
}
}
/// If this is an extension instance method, the tear off closure parameter
/// corresponding to the [index]th parameter on the instance method is
/// returned.
///
/// This is used to update the default value for the closure parameter when
/// it has been computed for the original parameter.
VariableDeclaration getExtensionTearOffParameter(int index) => null;
/// Returns the parameter for 'this' synthetically added to extension
/// instance members.
VariableDeclaration get extensionThis {
@@ -451,6 +473,14 @@ class ProcedureBuilder extends FunctionBuilder {
/// the synthetically created tear off function.
Procedure _extensionTearOff;
/// If this is an extension instance method then
/// [_extensionTearOffParameterMap] holds a map from the parameters of
/// the methods to the parameter of the closure returned in the tear-off.
///
/// This map is used to set the default values on the closure parameters when
/// these have been built.
Map<VariableDeclaration, VariableDeclaration> _extensionTearOffParameterMap;
ProcedureBuilder(
List<MetadataBuilder> metadata,
int modifiers,
@@ -585,6 +615,8 @@ class ProcedureBuilder extends FunctionBuilder {
_extensionTearOff != null, "No extension tear off created for $this.");
if (_extensionTearOff.name != null) return;
_extensionTearOffParameterMap = {};
int fileOffset = _procedure.fileOffset;
int extensionTypeParameterCount =
@@ -592,17 +624,18 @@ class ProcedureBuilder extends FunctionBuilder {
List<TypeParameter> typeParameters = <TypeParameter>[];
Map<TypeParameter, DartType> substitutionMap = {};
List<DartType> typeArguments = <DartType>[];
for (TypeParameter typeParameter in function.typeParameters) {
TypeParameter newTypeParameter = new TypeParameter(typeParameter.name);
typeParameters.add(newTypeParameter);
typeArguments.add(new TypeParameterType(newTypeParameter));
typeArguments.add(substitutionMap[typeParameter] =
new TypeParameterType(newTypeParameter));
}
List<TypeParameter> tearOffTypeParameters = <TypeParameter>[];
List<TypeParameter> closureTypeParameters = <TypeParameter>[];
Substitution substitution =
Substitution.fromPairs(function.typeParameters, typeArguments);
Substitution substitution = Substitution.fromMap(substitutionMap);
for (int index = 0; index < typeParameters.length; index++) {
TypeParameter newTypeParameter = typeParameters[index];
newTypeParameter.bound =
@@ -618,12 +651,11 @@ class ProcedureBuilder extends FunctionBuilder {
VariableDeclaration copyParameter(
VariableDeclaration parameter, DartType type,
{bool isOptional}) {
// TODO(johnniwinther): Handle default values.
return new VariableDeclaration(parameter.name,
type: type,
initializer: isOptional ? new NullLiteral() : null,
isFinal: parameter.isFinal)
VariableDeclaration newParameter = new VariableDeclaration(parameter.name,
type: type, isFinal: parameter.isFinal)
..fileOffset = parameter.fileOffset;
_extensionTearOffParameterMap[parameter] = newParameter;
return newParameter;
}
VariableDeclaration extensionThis = copyParameter(
@@ -697,6 +729,14 @@ class ProcedureBuilder extends FunctionBuilder {
_extensionTearOff.function.parent = _extensionTearOff;
}
@override
VariableDeclaration getExtensionTearOffParameter(int index) {
if (_extensionTearOffParameterMap != null) {
return _extensionTearOffParameterMap[getFormalParameter(index)];
}
return null;
}
/// The [Procedure] built by this builder.
Procedure get procedure => isPatch ? origin.procedure : _procedure;
@@ -789,18 +789,31 @@ class BodyBuilder extends ScopeListener<JumpTarget>
FormalParameterBuilder parameter = formals.parameters[i];
Expression initializer = parameter.target.initializer;
if (parameter.isOptional || initializer != null) {
VariableDeclaration realParameter = builder.formals[i].target;
if (parameter.isOptional) {
initializer ??= forest.createNullLiteral(
// TODO(ahe): Should store: realParameter.fileOffset
// TODO(ahe): Should store: originParameter.fileOffset
// https://github.com/dart-lang/sdk/issues/32289
null);
}
realParameter.initializer = initializer..parent = realParameter;
VariableDeclaration originParameter = builder.getFormalParameter(i);
originParameter.initializer = initializer..parent = originParameter;
typeInferrer?.inferParameterInitializer(
this, initializer, realParameter.type);
this, initializer, originParameter.type);
libraryBuilder.loader.transformPostInference(
realParameter, transformSetLiterals, transformCollections);
originParameter, transformSetLiterals, transformCollections);
VariableDeclaration extensionTearOffParameter =
builder.getExtensionTearOffParameter(i);
if (extensionTearOffParameter != null) {
cloner ??= new CloneVisitor();
Expression tearOffInitializer = cloner.clone(initializer);
extensionTearOffParameter.initializer = tearOffInitializer
..parent = extensionTearOffParameter;
libraryBuilder.loader.transformPostInference(
extensionTearOffParameter,
transformSetLiterals,
transformCollections);
}
}
}
}
@@ -0,0 +1,36 @@
// 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.
class Class {}
extension Extension on Class {
method0([a]) => a;
method1([a = 42]) => a;
method2({b = 87}) => b;
method3({c = staticMethod}) => c();
static staticMethod() => 123;
}
main() {
Class c = new Class();
var tearOff0 = c.method0;
expect(0, tearOff0(0));
expect(null, tearOff0());
var tearOff1 = c.method1;
expect(0, tearOff1(0));
expect(42, tearOff1());
var tearOff2 = c.method2;
expect(0, tearOff2(b: 0));
expect(87, tearOff2());
var tearOff3 = c.method3;
expect(0, tearOff3(c: () => 0));
expect(123, tearOff3());
}
expect(expected, actual) {
if (expected != actual) {
throw 'Mismatch: expected=$expected, actual=$actual';
}
}
@@ -0,0 +1,41 @@
library;
import self as self;
import "dart:core" as core;
class Class extends core::Object {
synthetic constructor •() → self::Class*
;
}
extension Extension on self::Class* {
method method0 = self::Extension|method0;
tearoff method0 = self::Extension|get#method0;
method method1 = self::Extension|method1;
tearoff method1 = self::Extension|get#method1;
method method2 = self::Extension|method2;
tearoff method2 = self::Extension|get#method2;
method method3 = self::Extension|method3;
tearoff method3 = self::Extension|get#method3;
static method staticMethod = self::Extension|staticMethod;
}
static method Extension|method0(final self::Class* #this, [dynamic a]) → dynamic
;
static method Extension|get#method0(final self::Class* #this) → ([dynamic]) →* dynamic
return ([dynamic a]) → dynamic => self::Extension|method0(#this, a);
static method Extension|method1(final self::Class* #this, [dynamic a]) → dynamic
;
static method Extension|get#method1(final self::Class* #this) → ([dynamic]) →* dynamic
return ([dynamic a]) → dynamic => self::Extension|method1(#this, a);
static method Extension|method2(final self::Class* #this, {dynamic b}) → dynamic
;
static method Extension|get#method2(final self::Class* #this) → ({b: dynamic}) →* dynamic
return ({dynamic b}) → dynamic => self::Extension|method2(#this, b: b);
static method Extension|method3(final self::Class* #this, {dynamic c}) → dynamic
;
static method Extension|get#method3(final self::Class* #this) → ({c: dynamic}) →* dynamic
return ({dynamic c}) → dynamic => self::Extension|method3(#this, c: c);
static method Extension|staticMethod() → dynamic
;
static method main() → dynamic
;
static method expect(dynamic expected, dynamic actual) → dynamic
;
@@ -0,0 +1,65 @@
library;
import self as self;
import "dart:core" as core;
class Class extends core::Object {
synthetic constructor •() → self::Class*
: super core::Object::•()
;
}
extension Extension on self::Class* {
method method0 = self::Extension|method0;
tearoff method0 = self::Extension|get#method0;
method method1 = self::Extension|method1;
tearoff method1 = self::Extension|get#method1;
method method2 = self::Extension|method2;
tearoff method2 = self::Extension|get#method2;
method method3 = self::Extension|method3;
tearoff method3 = self::Extension|get#method3;
static method staticMethod = self::Extension|staticMethod;
}
static method Extension|method0(final self::Class* #this, [dynamic a = #C1]) → dynamic
return a;
static method Extension|get#method0(final self::Class* #this) → ([dynamic]) →* dynamic
return ([dynamic a = #C1]) → dynamic => self::Extension|method0(#this, a);
static method Extension|method1(final self::Class* #this, [dynamic a = #C2]) → dynamic
return a;
static method Extension|get#method1(final self::Class* #this) → ([dynamic]) →* dynamic
return ([dynamic a = #C2]) → dynamic => self::Extension|method1(#this, a);
static method Extension|method2(final self::Class* #this, {dynamic b = #C3}) → dynamic
return b;
static method Extension|get#method2(final self::Class* #this) → ({b: dynamic}) →* dynamic
return ({dynamic b = #C3}) → dynamic => self::Extension|method2(#this, b: b);
static method Extension|method3(final self::Class* #this, {dynamic c = #C4}) → dynamic
return c.call();
static method Extension|get#method3(final self::Class* #this) → ({c: dynamic}) →* dynamic
return ({dynamic c = #C4}) → dynamic => self::Extension|method3(#this, c: c);
static method Extension|staticMethod() → dynamic
return 123;
static method main() → dynamic {
self::Class* c = new self::Class::•();
([dynamic]) →* dynamic tearOff0 = self::Extension|get#method0(c);
self::expect(0, tearOff0.call(0));
self::expect(null, tearOff0.call());
([dynamic]) →* dynamic tearOff1 = self::Extension|get#method1(c);
self::expect(0, tearOff1.call(0));
self::expect(42, tearOff1.call());
({b: dynamic}) →* dynamic tearOff2 = self::Extension|get#method2(c);
self::expect(0, tearOff2.call(b: 0));
self::expect(87, tearOff2.call());
({c: dynamic}) →* dynamic tearOff3 = self::Extension|get#method3(c);
self::expect(0, tearOff3.call(c: () → core::int* => 0));
self::expect(123, tearOff3.call());
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
throw "Mismatch: expected=${expected}, actual=${actual}";
}
}
constants {
#C1 = null
#C2 = 42
#C3 = 87
#C4 = tearoff self::Extension|staticMethod
}
@@ -0,0 +1,65 @@
library;
import self as self;
import "dart:core" as core;
class Class extends core::Object {
synthetic constructor •() → self::Class*
: super core::Object::•()
;
}
extension Extension on self::Class* {
method method0 = self::Extension|method0;
tearoff method0 = self::Extension|get#method0;
method method1 = self::Extension|method1;
tearoff method1 = self::Extension|get#method1;
method method2 = self::Extension|method2;
tearoff method2 = self::Extension|get#method2;
method method3 = self::Extension|method3;
tearoff method3 = self::Extension|get#method3;
static method staticMethod = self::Extension|staticMethod;
}
static method Extension|method0(final self::Class* #this, [dynamic a = #C1]) → dynamic
return a;
static method Extension|get#method0(final self::Class* #this) → ([dynamic]) →* dynamic
return ([dynamic a = #C1]) → dynamic => self::Extension|method0(#this, a);
static method Extension|method1(final self::Class* #this, [dynamic a = #C2]) → dynamic
return a;
static method Extension|get#method1(final self::Class* #this) → ([dynamic]) →* dynamic
return ([dynamic a = #C2]) → dynamic => self::Extension|method1(#this, a);
static method Extension|method2(final self::Class* #this, {dynamic b = #C3}) → dynamic
return b;
static method Extension|get#method2(final self::Class* #this) → ({b: dynamic}) →* dynamic
return ({dynamic b = #C3}) → dynamic => self::Extension|method2(#this, b: b);
static method Extension|method3(final self::Class* #this, {dynamic c = #C4}) → dynamic
return c.call();
static method Extension|get#method3(final self::Class* #this) → ({c: dynamic}) →* dynamic
return ({dynamic c = #C4}) → dynamic => self::Extension|method3(#this, c: c);
static method Extension|staticMethod() → dynamic
return 123;
static method main() → dynamic {
self::Class* c = new self::Class::•();
([dynamic]) →* dynamic tearOff0 = self::Extension|get#method0(c);
self::expect(0, tearOff0.call(0));
self::expect(null, tearOff0.call());
([dynamic]) →* dynamic tearOff1 = self::Extension|get#method1(c);
self::expect(0, tearOff1.call(0));
self::expect(42, tearOff1.call());
({b: dynamic}) →* dynamic tearOff2 = self::Extension|get#method2(c);
self::expect(0, tearOff2.call(b: 0));
self::expect(87, tearOff2.call());
({c: dynamic}) →* dynamic tearOff3 = self::Extension|get#method3(c);
self::expect(0, tearOff3.call(c: () → core::int* => 0));
self::expect(123, tearOff3.call());
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
throw "Mismatch: expected=${expected}, actual=${actual}";
}
}
constants {
#C1 = null
#C2 = 42
#C3 = 87
#C4 = tearoff self::Extension|staticMethod
}
@@ -76,11 +76,11 @@ static method Extension|get#writeSetterRequired(final self::Class* #this) → (d
static method Extension|writeSetterOptional(final self::Class* #this, [dynamic value]) → dynamic
;
static method Extension|get#writeSetterOptional(final self::Class* #this) → ([dynamic]) →* dynamic
return ([dynamic value = null]) → dynamic => self::Extension|writeSetterOptional(#this, value);
return ([dynamic value]) → dynamic => self::Extension|writeSetterOptional(#this, value);
static method Extension|writeSetterNamed(final self::Class* #this, {dynamic value}) → dynamic
;
static method Extension|get#writeSetterNamed(final self::Class* #this) → ({value: dynamic}) →* dynamic
return ({dynamic value = null}) → dynamic => self::Extension|writeSetterNamed(#this, value: value);
return ({dynamic value}) → dynamic => self::Extension|writeSetterNamed(#this, value: value);
static method Extension|get#tearOffGetterNoArgs(final self::Class* #this) → dynamic
;
static method Extension|get#tearOffGetterRequired(final self::Class* #this) → dynamic
@@ -116,11 +116,11 @@ static method GenericExtension|get#writeSetterRequired<T extends core::Object* =
static method GenericExtension|writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterOptional::T*>* #this, [self::GenericExtension|writeSetterOptional::T* value]) → dynamic
;
static method GenericExtension|get#writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterOptional::T*>* #this) → ([self::GenericExtension|get#writeSetterOptional::T*]) →* dynamic
return ([self::GenericExtension|get#writeSetterOptional::T* value = null]) → dynamic => self::GenericExtension|writeSetterOptional<self::GenericExtension|get#writeSetterOptional::T*>(#this, value);
return ([self::GenericExtension|get#writeSetterOptional::T* value]) → dynamic => self::GenericExtension|writeSetterOptional<self::GenericExtension|get#writeSetterOptional::T*>(#this, value);
static method GenericExtension|writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterNamed::T*>* #this, {self::GenericExtension|writeSetterNamed::T* value}) → dynamic
;
static method GenericExtension|get#writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterNamed::T*>* #this) → ({value: self::GenericExtension|get#writeSetterNamed::T*}) →* dynamic
return ({self::GenericExtension|get#writeSetterNamed::T* value = null}) → dynamic => self::GenericExtension|writeSetterNamed<self::GenericExtension|get#writeSetterNamed::T*>(#this, value: value);
return ({self::GenericExtension|get#writeSetterNamed::T* value}) → dynamic => self::GenericExtension|writeSetterNamed<self::GenericExtension|get#writeSetterNamed::T*>(#this, value: value);
static method GenericExtension|genericWriteSetterRequired<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterRequired::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterRequired::T*>* #this, self::GenericExtension|genericWriteSetterRequired::S* value) → dynamic
;
static method GenericExtension|get#genericWriteSetterRequired<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterRequired::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterRequired::T* = dynamic>(S*) →* dynamic
@@ -128,9 +128,9 @@ static method GenericExtension|get#genericWriteSetterRequired<T extends core::Ob
static method GenericExtension|genericWriteSetterOptional<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterOptional::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterOptional::T*>* #this, [self::GenericExtension|genericWriteSetterOptional::S* value]) → dynamic
;
static method GenericExtension|get#genericWriteSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterOptional::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S*]) →* dynamic
return <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S* value = null]) → dynamic => self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|get#genericWriteSetterOptional::T*, S*>(#this, value);
return <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S* value]) → dynamic => self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|get#genericWriteSetterOptional::T*, S*>(#this, value);
static method GenericExtension|get#genericWriteSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterNamed::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({value: S*}) →* dynamic
return <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({S* value = null}) → dynamic => self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|get#genericWriteSetterNamed::T*, S*>(#this, value: value);
return <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({S* value}) → dynamic => self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|get#genericWriteSetterNamed::T*, S*>(#this, value: value);
static method GenericExtension|genericWriteSetterNamed<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterNamed::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterNamed::T*>* #this, {self::GenericExtension|genericWriteSetterNamed::S* value}) → dynamic
;
static method GenericExtension|get#property<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#property::T*>* #this) → self::GenericExtension|get#property::T*
@@ -77,12 +77,12 @@ static method Extension|writeSetterRequired(final self::Class* #this, dynamic va
}
static method Extension|get#writeSetterRequired(final self::Class* #this) → (dynamic) →* dynamic
return (dynamic value) → dynamic => self::Extension|writeSetterRequired(#this, value);
static method Extension|writeSetterOptional(final self::Class* #this = #C1, [dynamic value = #C1]) → dynamic {
static method Extension|writeSetterOptional(final self::Class* #this, [dynamic value = #C1]) → dynamic {
self::Extension|set#property(#this, value);
}
static method Extension|get#writeSetterOptional(final self::Class* #this) → ([dynamic]) →* dynamic
return ([dynamic value = #C1]) → dynamic => self::Extension|writeSetterOptional(#this, value);
static method Extension|writeSetterNamed(final self::Class* #this = #C1, {dynamic value = #C1}) → dynamic {
static method Extension|writeSetterNamed(final self::Class* #this, {dynamic value = #C1}) → dynamic {
self::Extension|set#property(#this, value);
}
static method Extension|get#writeSetterNamed(final self::Class* #this) → ({value: dynamic}) →* dynamic
@@ -144,12 +144,12 @@ static method GenericExtension|writeSetterRequired<T extends core::Object* = dyn
}
static method GenericExtension|get#writeSetterRequired<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterRequired::T*>* #this) → (self::GenericExtension|get#writeSetterRequired::T*) →* dynamic
return (self::GenericExtension|get#writeSetterRequired::T* value) → dynamic => self::GenericExtension|writeSetterRequired<self::GenericExtension|get#writeSetterRequired::T*>(#this, value);
static method GenericExtension|writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterOptional::T*>* #this = #C1, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic {
static method GenericExtension|writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterOptional::T*>* #this, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic {
self::GenericExtension|set#property<self::GenericExtension|writeSetterOptional::T*>(#this, value);
}
static method GenericExtension|get#writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterOptional::T*>* #this) → ([self::GenericExtension|get#writeSetterOptional::T*]) →* dynamic
return ([self::GenericExtension|get#writeSetterOptional::T* value = #C1]) → dynamic => self::GenericExtension|writeSetterOptional<self::GenericExtension|get#writeSetterOptional::T*>(#this, value);
static method GenericExtension|writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterNamed::T*>* #this = #C1, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic {
static method GenericExtension|writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterNamed::T*>* #this, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic {
self::GenericExtension|set#property<self::GenericExtension|writeSetterNamed::T*>(#this, value);
}
static method GenericExtension|get#writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterNamed::T*>* #this) → ({value: self::GenericExtension|get#writeSetterNamed::T*}) →* dynamic
@@ -159,14 +159,14 @@ static method GenericExtension|genericWriteSetterRequired<T extends core::Object
}
static method GenericExtension|get#genericWriteSetterRequired<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterRequired::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterRequired::T* = dynamic>(S*) →* dynamic
return <S extends self::GenericExtension|get#genericWriteSetterRequired::T* = dynamic>(S* value) → dynamic => self::GenericExtension|genericWriteSetterRequired<self::GenericExtension|get#genericWriteSetterRequired::T*, S*>(#this, value);
static method GenericExtension|genericWriteSetterOptional<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterOptional::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterOptional::T*>* #this = #C1, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic {
static method GenericExtension|genericWriteSetterOptional<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterOptional::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterOptional::T*>* #this, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic {
self::GenericExtension|set#property<self::GenericExtension|genericWriteSetterOptional::T*>(#this, value);
}
static method GenericExtension|get#genericWriteSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterOptional::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S*]) →* dynamic
return <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S* value = #C1]) → dynamic => self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|get#genericWriteSetterOptional::T*, S*>(#this, value);
static method GenericExtension|get#genericWriteSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterNamed::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({value: S*}) →* dynamic
return <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({S* value = #C1}) → dynamic => self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|get#genericWriteSetterNamed::T*, S*>(#this, value: value);
static method GenericExtension|genericWriteSetterNamed<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterNamed::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterNamed::T*>* #this = #C1, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic {
static method GenericExtension|genericWriteSetterNamed<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterNamed::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterNamed::T*>* #this, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic {
self::GenericExtension|set#property<self::GenericExtension|genericWriteSetterNamed::T*>(#this, value);
}
static method GenericExtension|get#property<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#property::T*>* #this) → self::GenericExtension|get#property::T*
@@ -77,12 +77,12 @@ static method Extension|writeSetterRequired(final self::Class* #this, dynamic va
}
static method Extension|get#writeSetterRequired(final self::Class* #this) → (dynamic) →* dynamic
return (dynamic value) → dynamic => self::Extension|writeSetterRequired(#this, value);
static method Extension|writeSetterOptional(final self::Class* #this = #C1, [dynamic value = #C1]) → dynamic {
static method Extension|writeSetterOptional(final self::Class* #this, [dynamic value = #C1]) → dynamic {
self::Extension|set#property(#this, value);
}
static method Extension|get#writeSetterOptional(final self::Class* #this) → ([dynamic]) →* dynamic
return ([dynamic value = #C1]) → dynamic => self::Extension|writeSetterOptional(#this, value);
static method Extension|writeSetterNamed(final self::Class* #this = #C1, {dynamic value = #C1}) → dynamic {
static method Extension|writeSetterNamed(final self::Class* #this, {dynamic value = #C1}) → dynamic {
self::Extension|set#property(#this, value);
}
static method Extension|get#writeSetterNamed(final self::Class* #this) → ({value: dynamic}) →* dynamic
@@ -144,12 +144,12 @@ static method GenericExtension|writeSetterRequired<T extends core::Object* = dyn
}
static method GenericExtension|get#writeSetterRequired<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterRequired::T*>* #this) → (self::GenericExtension|get#writeSetterRequired::T*) →* dynamic
return (self::GenericExtension|get#writeSetterRequired::T* value) → dynamic => self::GenericExtension|writeSetterRequired<self::GenericExtension|get#writeSetterRequired::T*>(#this, value);
static method GenericExtension|writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterOptional::T*>* #this = #C1, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic {
static method GenericExtension|writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterOptional::T*>* #this, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic {
self::GenericExtension|set#property<self::GenericExtension|writeSetterOptional::T*>(#this, value);
}
static method GenericExtension|get#writeSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterOptional::T*>* #this) → ([self::GenericExtension|get#writeSetterOptional::T*]) →* dynamic
return ([self::GenericExtension|get#writeSetterOptional::T* value = #C1]) → dynamic => self::GenericExtension|writeSetterOptional<self::GenericExtension|get#writeSetterOptional::T*>(#this, value);
static method GenericExtension|writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterNamed::T*>* #this = #C1, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic {
static method GenericExtension|writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|writeSetterNamed::T*>* #this, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic {
self::GenericExtension|set#property<self::GenericExtension|writeSetterNamed::T*>(#this, value);
}
static method GenericExtension|get#writeSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#writeSetterNamed::T*>* #this) → ({value: self::GenericExtension|get#writeSetterNamed::T*}) →* dynamic
@@ -159,14 +159,14 @@ static method GenericExtension|genericWriteSetterRequired<T extends core::Object
}
static method GenericExtension|get#genericWriteSetterRequired<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterRequired::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterRequired::T* = dynamic>(S*) →* dynamic
return <S extends self::GenericExtension|get#genericWriteSetterRequired::T* = dynamic>(S* value) → dynamic => self::GenericExtension|genericWriteSetterRequired<self::GenericExtension|get#genericWriteSetterRequired::T*, S*>(#this, value);
static method GenericExtension|genericWriteSetterOptional<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterOptional::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterOptional::T*>* #this = #C1, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic {
static method GenericExtension|genericWriteSetterOptional<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterOptional::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterOptional::T*>* #this, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic {
self::GenericExtension|set#property<self::GenericExtension|genericWriteSetterOptional::T*>(#this, value);
}
static method GenericExtension|get#genericWriteSetterOptional<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterOptional::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S*]) →* dynamic
return <S extends self::GenericExtension|get#genericWriteSetterOptional::T* = dynamic>([S* value = #C1]) → dynamic => self::GenericExtension|genericWriteSetterOptional<self::GenericExtension|get#genericWriteSetterOptional::T*, S*>(#this, value);
static method GenericExtension|get#genericWriteSetterNamed<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#genericWriteSetterNamed::T*>* #this) → <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({value: S*}) →* dynamic
return <S extends self::GenericExtension|get#genericWriteSetterNamed::T* = dynamic>({S* value = #C1}) → dynamic => self::GenericExtension|genericWriteSetterNamed<self::GenericExtension|get#genericWriteSetterNamed::T*, S*>(#this, value: value);
static method GenericExtension|genericWriteSetterNamed<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterNamed::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterNamed::T*>* #this = #C1, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic {
static method GenericExtension|genericWriteSetterNamed<T extends core::Object* = dynamic, S extends self::GenericExtension|genericWriteSetterNamed::T* = dynamic>(final self::GenericClass<self::GenericExtension|genericWriteSetterNamed::T*>* #this, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic {
self::GenericExtension|set#property<self::GenericExtension|genericWriteSetterNamed::T*>(#this, value);
}
static method GenericExtension|get#property<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#property::T*>* #this) → self::GenericExtension|get#property::T*
@@ -37,11 +37,11 @@ static method A2|get#method2(final self::A1* #this) → <T extends core::Object*
static method A2|method3<T extends core::Object* = dynamic>(final self::A1* #this, [self::A2|method3::T* o]) → self::A1*
;
static method A2|get#method3(final self::A1* #this) → <T extends core::Object* = dynamic>([T*]) →* self::A1*
return <T extends core::Object* = dynamic>([T* o = null]) → self::A1* => self::A2|method3<T*>(#this, o);
return <T extends core::Object* = dynamic>([T* o]) → self::A1* => self::A2|method3<T*>(#this, o);
static method A2|method4<T extends core::Object* = dynamic>(final self::A1* #this, {self::A2|method4::T* o}) → self::A1*
;
static method A2|get#method4(final self::A1* #this) → <T extends core::Object* = dynamic>({o: T*}) →* self::A1*
return <T extends core::Object* = dynamic>({T* o = null}) → self::A1* => self::A2|method4<T*>(#this, o: o);
return <T extends core::Object* = dynamic>({T* o}) → self::A1* => self::A2|method4<T*>(#this, o: o);
static method B2|method1<T extends core::Object* = dynamic>(final self::B1<self::B2|method1::T*>* #this) → self::B1<self::B2|method1::T*>*
;
static method B2|get#method1<T extends core::Object* = dynamic>(final self::B1<self::B2|get#method1::T*>* #this) → () →* self::B1<self::B2|get#method1::T*>*
@@ -39,13 +39,13 @@ static method A2|method2<T extends core::Object* = dynamic>(final self::A1* #thi
}
static method A2|get#method2(final self::A1* #this) → <T extends core::Object* = dynamic>(T*) →* self::A1*
return <T extends core::Object* = dynamic>(T* o) → self::A1* => self::A2|method2<T*>(#this, o);
static method A2|method3<T extends core::Object* = dynamic>(final self::A1* #this = #C1, [self::A2|method3::T* o = #C1]) → self::A1* {
static method A2|method3<T extends core::Object* = dynamic>(final self::A1* #this, [self::A2|method3::T* o = #C1]) → self::A1* {
core::print(o);
return #this;
}
static method A2|get#method3(final self::A1* #this) → <T extends core::Object* = dynamic>([T*]) →* self::A1*
return <T extends core::Object* = dynamic>([T* o = #C1]) → self::A1* => self::A2|method3<T*>(#this, o);
static method A2|method4<T extends core::Object* = dynamic>(final self::A1* #this = #C1, {self::A2|method4::T* o = #C1}) → self::A1* {
static method A2|method4<T extends core::Object* = dynamic>(final self::A1* #this, {self::A2|method4::T* o = #C1}) → self::A1* {
core::print(o);
return #this;
}
@@ -39,13 +39,13 @@ static method A2|method2<T extends core::Object* = dynamic>(final self::A1* #thi
}
static method A2|get#method2(final self::A1* #this) → <T extends core::Object* = dynamic>(T*) →* self::A1*
return <T extends core::Object* = dynamic>(T* o) → self::A1* => self::A2|method2<T*>(#this, o);
static method A2|method3<T extends core::Object* = dynamic>(final self::A1* #this = #C1, [self::A2|method3::T* o = #C1]) → self::A1* {
static method A2|method3<T extends core::Object* = dynamic>(final self::A1* #this, [self::A2|method3::T* o = #C1]) → self::A1* {
core::print(o);
return #this;
}
static method A2|get#method3(final self::A1* #this) → <T extends core::Object* = dynamic>([T*]) →* self::A1*
return <T extends core::Object* = dynamic>([T* o = #C1]) → self::A1* => self::A2|method3<T*>(#this, o);
static method A2|method4<T extends core::Object* = dynamic>(final self::A1* #this = #C1, {self::A2|method4::T* o = #C1}) → self::A1* {
static method A2|method4<T extends core::Object* = dynamic>(final self::A1* #this, {self::A2|method4::T* o = #C1}) → self::A1* {
core::print(o);
return #this;
}
@@ -12,6 +12,7 @@ expression/main: TextSerializationFailure # Was: Pass
extensions/annotations: TextSerializationFailure
extensions/compounds: TextSerializationFailure
extensions/conflicts: TextSerializationFailure
extensions/default_values: TextSerializationFailure
extensions/direct_instance_access: TextSerializationFailure
extensions/direct_static_access: TextSerializationFailure
extensions/dynamic_invoke: TextSerializationFailure
+2
View File
@@ -11,6 +11,8 @@ class Class {
extension Extension on Class {
int method() => this.field;
int methodWithOptionals([int a = 42]) => a;
int get property => this.field;
void set property(int value) {
@@ -24,10 +24,15 @@ testExplicitAccess(Class c) {
testImplicitAccess(Class c) {
Expect.equals(c.field, c.method());
Expect.equals(42, c.methodWithOptionals());
Expect.equals(123, c.methodWithOptionals(123));
Expect.equals(c.field, c.property);
Expect.equals(123, c.property = 123);
var f = c.method;
Expect.equals(c.field, f());
var f2 = c.methodWithOptionals;
Expect.equals(42, f2());
Expect.equals(87, f2(87));
}
testStaticAccess() {