diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart index d6c3eca24e0..d818e4d07a2 100644 --- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart +++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart @@ -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 _extensionTearOffParameterMap; + ProcedureBuilder( List 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 typeParameters = []; + Map substitutionMap = {}; List typeArguments = []; 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 tearOffTypeParameters = []; List closureTypeParameters = []; - 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; diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart index 9b9e060b74a..980cceba539 100644 --- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart @@ -789,18 +789,31 @@ class BodyBuilder extends ScopeListener 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); + } } } } diff --git a/pkg/front_end/testcases/extensions/default_values.dart b/pkg/front_end/testcases/extensions/default_values.dart new file mode 100644 index 00000000000..0b08f6de232 --- /dev/null +++ b/pkg/front_end/testcases/extensions/default_values.dart @@ -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'; + } +} \ No newline at end of file diff --git a/pkg/front_end/testcases/extensions/default_values.dart.outline.expect b/pkg/front_end/testcases/extensions/default_values.dart.outline.expect new file mode 100644 index 00000000000..77ed4f468f7 --- /dev/null +++ b/pkg/front_end/testcases/extensions/default_values.dart.outline.expect @@ -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 + ; diff --git a/pkg/front_end/testcases/extensions/default_values.dart.strong.expect b/pkg/front_end/testcases/extensions/default_values.dart.strong.expect new file mode 100644 index 00000000000..e6b8869400f --- /dev/null +++ b/pkg/front_end/testcases/extensions/default_values.dart.strong.expect @@ -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 +} diff --git a/pkg/front_end/testcases/extensions/default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/default_values.dart.strong.transformed.expect new file mode 100644 index 00000000000..e6b8869400f --- /dev/null +++ b/pkg/front_end/testcases/extensions/default_values.dart.strong.transformed.expect @@ -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 +} diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart.outline.expect b/pkg/front_end/testcases/extensions/direct_instance_access.dart.outline.expect index 86ff6e693a1..f38f7f8cb68 100644 --- a/pkg/front_end/testcases/extensions/direct_instance_access.dart.outline.expect +++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart.outline.expect @@ -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(final self::GenericClass* #this, [self::GenericExtension|writeSetterOptional::T* value]) → dynamic ; static method GenericExtension|get#writeSetterOptional(final self::GenericClass* #this) → ([self::GenericExtension|get#writeSetterOptional::T*]) →* dynamic - return ([self::GenericExtension|get#writeSetterOptional::T* value = null]) → dynamic => self::GenericExtension|writeSetterOptional(#this, value); + return ([self::GenericExtension|get#writeSetterOptional::T* value]) → dynamic => self::GenericExtension|writeSetterOptional(#this, value); static method GenericExtension|writeSetterNamed(final self::GenericClass* #this, {self::GenericExtension|writeSetterNamed::T* value}) → dynamic ; static method GenericExtension|get#writeSetterNamed(final self::GenericClass* #this) → ({value: self::GenericExtension|get#writeSetterNamed::T*}) →* dynamic - return ({self::GenericExtension|get#writeSetterNamed::T* value = null}) → dynamic => self::GenericExtension|writeSetterNamed(#this, value: value); + return ({self::GenericExtension|get#writeSetterNamed::T* value}) → dynamic => self::GenericExtension|writeSetterNamed(#this, value: value); static method GenericExtension|genericWriteSetterRequired(final self::GenericClass* #this, self::GenericExtension|genericWriteSetterRequired::S* value) → dynamic ; static method GenericExtension|get#genericWriteSetterRequired(final self::GenericClass* #this) → (S*) →* dynamic @@ -128,9 +128,9 @@ static method GenericExtension|get#genericWriteSetterRequired(final self::GenericClass* #this, [self::GenericExtension|genericWriteSetterOptional::S* value]) → dynamic ; static method GenericExtension|get#genericWriteSetterOptional(final self::GenericClass* #this) → ([S*]) →* dynamic - return ([S* value = null]) → dynamic => self::GenericExtension|genericWriteSetterOptional(#this, value); + return ([S* value]) → dynamic => self::GenericExtension|genericWriteSetterOptional(#this, value); static method GenericExtension|get#genericWriteSetterNamed(final self::GenericClass* #this) → ({value: S*}) →* dynamic - return ({S* value = null}) → dynamic => self::GenericExtension|genericWriteSetterNamed(#this, value: value); + return ({S* value}) → dynamic => self::GenericExtension|genericWriteSetterNamed(#this, value: value); static method GenericExtension|genericWriteSetterNamed(final self::GenericClass* #this, {self::GenericExtension|genericWriteSetterNamed::S* value}) → dynamic ; static method GenericExtension|get#property(final self::GenericClass* #this) → self::GenericExtension|get#property::T* diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.expect b/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.expect index 5cdf5f93754..ee8966fee81 100644 --- a/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.expect +++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.expect @@ -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(final self::GenericClass* #this) → (self::GenericExtension|get#writeSetterRequired::T*) →* dynamic return (self::GenericExtension|get#writeSetterRequired::T* value) → dynamic => self::GenericExtension|writeSetterRequired(#this, value); -static method GenericExtension|writeSetterOptional(final self::GenericClass* #this = #C1, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic { +static method GenericExtension|writeSetterOptional(final self::GenericClass* #this, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic { self::GenericExtension|set#property(#this, value); } static method GenericExtension|get#writeSetterOptional(final self::GenericClass* #this) → ([self::GenericExtension|get#writeSetterOptional::T*]) →* dynamic return ([self::GenericExtension|get#writeSetterOptional::T* value = #C1]) → dynamic => self::GenericExtension|writeSetterOptional(#this, value); -static method GenericExtension|writeSetterNamed(final self::GenericClass* #this = #C1, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic { +static method GenericExtension|writeSetterNamed(final self::GenericClass* #this, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic { self::GenericExtension|set#property(#this, value); } static method GenericExtension|get#writeSetterNamed(final self::GenericClass* #this) → ({value: self::GenericExtension|get#writeSetterNamed::T*}) →* dynamic @@ -159,14 +159,14 @@ static method GenericExtension|genericWriteSetterRequired(final self::GenericClass* #this) → (S*) →* dynamic return (S* value) → dynamic => self::GenericExtension|genericWriteSetterRequired(#this, value); -static method GenericExtension|genericWriteSetterOptional(final self::GenericClass* #this = #C1, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic { +static method GenericExtension|genericWriteSetterOptional(final self::GenericClass* #this, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic { self::GenericExtension|set#property(#this, value); } static method GenericExtension|get#genericWriteSetterOptional(final self::GenericClass* #this) → ([S*]) →* dynamic return ([S* value = #C1]) → dynamic => self::GenericExtension|genericWriteSetterOptional(#this, value); static method GenericExtension|get#genericWriteSetterNamed(final self::GenericClass* #this) → ({value: S*}) →* dynamic return ({S* value = #C1}) → dynamic => self::GenericExtension|genericWriteSetterNamed(#this, value: value); -static method GenericExtension|genericWriteSetterNamed(final self::GenericClass* #this = #C1, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic { +static method GenericExtension|genericWriteSetterNamed(final self::GenericClass* #this, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic { self::GenericExtension|set#property(#this, value); } static method GenericExtension|get#property(final self::GenericClass* #this) → self::GenericExtension|get#property::T* diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.transformed.expect index 5cdf5f93754..ee8966fee81 100644 --- a/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart.strong.transformed.expect @@ -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(final self::GenericClass* #this) → (self::GenericExtension|get#writeSetterRequired::T*) →* dynamic return (self::GenericExtension|get#writeSetterRequired::T* value) → dynamic => self::GenericExtension|writeSetterRequired(#this, value); -static method GenericExtension|writeSetterOptional(final self::GenericClass* #this = #C1, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic { +static method GenericExtension|writeSetterOptional(final self::GenericClass* #this, [self::GenericExtension|writeSetterOptional::T* value = #C1]) → dynamic { self::GenericExtension|set#property(#this, value); } static method GenericExtension|get#writeSetterOptional(final self::GenericClass* #this) → ([self::GenericExtension|get#writeSetterOptional::T*]) →* dynamic return ([self::GenericExtension|get#writeSetterOptional::T* value = #C1]) → dynamic => self::GenericExtension|writeSetterOptional(#this, value); -static method GenericExtension|writeSetterNamed(final self::GenericClass* #this = #C1, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic { +static method GenericExtension|writeSetterNamed(final self::GenericClass* #this, {self::GenericExtension|writeSetterNamed::T* value = #C1}) → dynamic { self::GenericExtension|set#property(#this, value); } static method GenericExtension|get#writeSetterNamed(final self::GenericClass* #this) → ({value: self::GenericExtension|get#writeSetterNamed::T*}) →* dynamic @@ -159,14 +159,14 @@ static method GenericExtension|genericWriteSetterRequired(final self::GenericClass* #this) → (S*) →* dynamic return (S* value) → dynamic => self::GenericExtension|genericWriteSetterRequired(#this, value); -static method GenericExtension|genericWriteSetterOptional(final self::GenericClass* #this = #C1, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic { +static method GenericExtension|genericWriteSetterOptional(final self::GenericClass* #this, [self::GenericExtension|genericWriteSetterOptional::S* value = #C1]) → dynamic { self::GenericExtension|set#property(#this, value); } static method GenericExtension|get#genericWriteSetterOptional(final self::GenericClass* #this) → ([S*]) →* dynamic return ([S* value = #C1]) → dynamic => self::GenericExtension|genericWriteSetterOptional(#this, value); static method GenericExtension|get#genericWriteSetterNamed(final self::GenericClass* #this) → ({value: S*}) →* dynamic return ({S* value = #C1}) → dynamic => self::GenericExtension|genericWriteSetterNamed(#this, value: value); -static method GenericExtension|genericWriteSetterNamed(final self::GenericClass* #this = #C1, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic { +static method GenericExtension|genericWriteSetterNamed(final self::GenericClass* #this, {self::GenericExtension|genericWriteSetterNamed::S* value = #C1}) → dynamic { self::GenericExtension|set#property(#this, value); } static method GenericExtension|get#property(final self::GenericClass* #this) → self::GenericExtension|get#property::T* diff --git a/pkg/front_end/testcases/extensions/instance_members.dart.outline.expect b/pkg/front_end/testcases/extensions/instance_members.dart.outline.expect index 36c0330f9e7..09050c71b62 100644 --- a/pkg/front_end/testcases/extensions/instance_members.dart.outline.expect +++ b/pkg/front_end/testcases/extensions/instance_members.dart.outline.expect @@ -37,11 +37,11 @@ static method A2|get#method2(final self::A1* #this) → (final self::A1* #this, [self::A2|method3::T* o]) → self::A1* ; static method A2|get#method3(final self::A1* #this) → ([T*]) →* self::A1* - return ([T* o = null]) → self::A1* => self::A2|method3(#this, o); + return ([T* o]) → self::A1* => self::A2|method3(#this, o); static method A2|method4(final self::A1* #this, {self::A2|method4::T* o}) → self::A1* ; static method A2|get#method4(final self::A1* #this) → ({o: T*}) →* self::A1* - return ({T* o = null}) → self::A1* => self::A2|method4(#this, o: o); + return ({T* o}) → self::A1* => self::A2|method4(#this, o: o); static method B2|method1(final self::B1* #this) → self::B1* ; static method B2|get#method1(final self::B1* #this) → () →* self::B1* diff --git a/pkg/front_end/testcases/extensions/instance_members.dart.strong.expect b/pkg/front_end/testcases/extensions/instance_members.dart.strong.expect index dfed3fb1062..5b79a6bd0ab 100644 --- a/pkg/front_end/testcases/extensions/instance_members.dart.strong.expect +++ b/pkg/front_end/testcases/extensions/instance_members.dart.strong.expect @@ -39,13 +39,13 @@ static method A2|method2(final self::A1* #thi } static method A2|get#method2(final self::A1* #this) → (T*) →* self::A1* return (T* o) → self::A1* => self::A2|method2(#this, o); -static method A2|method3(final self::A1* #this = #C1, [self::A2|method3::T* o = #C1]) → self::A1* { +static method A2|method3(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*]) →* self::A1* return ([T* o = #C1]) → self::A1* => self::A2|method3(#this, o); -static method A2|method4(final self::A1* #this = #C1, {self::A2|method4::T* o = #C1}) → self::A1* { +static method A2|method4(final self::A1* #this, {self::A2|method4::T* o = #C1}) → self::A1* { core::print(o); return #this; } diff --git a/pkg/front_end/testcases/extensions/instance_members.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/instance_members.dart.strong.transformed.expect index dfed3fb1062..5b79a6bd0ab 100644 --- a/pkg/front_end/testcases/extensions/instance_members.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/extensions/instance_members.dart.strong.transformed.expect @@ -39,13 +39,13 @@ static method A2|method2(final self::A1* #thi } static method A2|get#method2(final self::A1* #this) → (T*) →* self::A1* return (T* o) → self::A1* => self::A2|method2(#this, o); -static method A2|method3(final self::A1* #this = #C1, [self::A2|method3::T* o = #C1]) → self::A1* { +static method A2|method3(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*]) →* self::A1* return ([T* o = #C1]) → self::A1* => self::A2|method3(#this, o); -static method A2|method4(final self::A1* #this = #C1, {self::A2|method4::T* o = #C1}) → self::A1* { +static method A2|method4(final self::A1* #this, {self::A2|method4::T* o = #C1}) → self::A1* { core::print(o); return #this; } diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status index aba162c1933..95610cc1aa4 100644 --- a/pkg/front_end/testcases/text_serialization.status +++ b/pkg/front_end/testcases/text_serialization.status @@ -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 diff --git a/tests/modular/extension_methods/def.dart b/tests/modular/extension_methods/def.dart index 665da3d8daa..d58df3b4864 100644 --- a/tests/modular/extension_methods/def.dart +++ b/tests/modular/extension_methods/def.dart @@ -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) { diff --git a/tests/modular/extension_methods/main.dart b/tests/modular/extension_methods/main.dart index 760cc854466..cb1801852b1 100644 --- a/tests/modular/extension_methods/main.dart +++ b/tests/modular/extension_methods/main.dart @@ -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() {