| // Copyright (c) 2026, 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:expect/expect.dart'; | |
| final int opaqueOne = int.parse('1'); | |
| void main() { | |
| final d = Derived<String>("hello", 42 * opaqueOne); | |
| Expect.equals("hello", d.t); | |
| Expect.equals(42, d.u); | |
| Expect.equals("hello", d.v); | |
| Expect.isTrue(d.t is String); | |
| Expect.isTrue(d.u is int); | |
| { | |
| final c = InitCapture(10 * opaqueOne); | |
| Expect.equals(10, c.getP()); | |
| } | |
| { | |
| final c = BodyCapture(20 * opaqueOne); | |
| Expect.equals(20, c.getP()); | |
| } | |
| { | |
| final c = BodyCaptureType<num>(opaqueOne); | |
| Expect.equals(1, c.p); | |
| Expect.equals(num, c.getT()); | |
| } | |
| { | |
| final c = BodyCaptureParamField(opaqueOne); | |
| Expect.equals(1, c.p); | |
| Expect.equals(1, c.getP()); | |
| } | |
| { | |
| final c = InitCaptureModify(30 * opaqueOne); | |
| Expect.equals(32, c.pAfter); | |
| Expect.equals(33, c.getP()); | |
| Expect.equals(34, c.getP()); | |
| } | |
| { | |
| final c = BodyCaptureModify(40 * opaqueOne); | |
| Expect.equals(50, c.pInBody); | |
| Expect.equals(51, c.getP()); | |
| Expect.equals(52, c.getP()); | |
| } | |
| { | |
| final c = InitStoreModify(60 * opaqueOne); | |
| Expect.equals(60, c.field1); | |
| Expect.equals(61, c.field2); | |
| } | |
| { | |
| final c = BodyModify(70 * opaqueOne); | |
| Expect.equals(70, c.field); | |
| Expect.equals(170, c.finalP); | |
| } | |
| { | |
| final c = SuperDerived(90 * opaqueOne); | |
| Expect.equals(90, c.y); | |
| Expect.equals(91, c.x); | |
| } | |
| { | |
| final c = ModifyInInitAndUseInBody(100 * opaqueOne); | |
| Expect.equals(101, c.inInit); | |
| Expect.equals(101, c.inBody); | |
| } | |
| { | |
| final c = CaptureInInitModifyInBody(200 * opaqueOne); | |
| Expect.equals(210, c.inBody); | |
| Expect.equals(210, c.closure()); | |
| } | |
| { | |
| final c = DoubleCapture(300 * opaqueOne); | |
| Expect.equals(310, c.initClosure()); | |
| Expect.equals(310, c.bodyClosure()); | |
| } | |
| { | |
| final c1 = MixedParams(opaqueOne); | |
| Expect.equals(1, c1.a); | |
| Expect.equals(2, c1.b); | |
| Expect.equals(3, c1.c); | |
| final c2 = MixedParams(opaqueOne, 10 * opaqueOne); | |
| Expect.equals(1, c2.a); | |
| Expect.equals(10, c2.b); | |
| Expect.equals(3, c2.c); | |
| } | |
| { | |
| final c1 = NamedParams(a: 5 * opaqueOne); | |
| Expect.equals(5, c1.a); | |
| Expect.equals(20, c1.b); | |
| final c2 = NamedParams(b: 30 * opaqueOne, a: 7 * opaqueOne); | |
| Expect.equals(7, c2.a); | |
| Expect.equals(30, c2.b); | |
| } | |
| { | |
| final c = RedirectDerived(10 * opaqueOne, 20 * opaqueOne); | |
| Expect.equals(30, c.c); | |
| Expect.equals(10, c.a); | |
| Expect.equals(11, c.b); | |
| } | |
| { | |
| final c = FactoryClass(50 * opaqueOne); | |
| Expect.equals(150, c.x); | |
| } | |
| { | |
| final c = MultiUse(400 * opaqueOne); | |
| Expect.equals(400, c.a); | |
| Expect.equals(401, c.b); | |
| Expect.equals(401, c.c); | |
| } | |
| { | |
| final c = CaptureAndModifyInInit(500 * opaqueOne); | |
| Expect.equals(505, c.field); | |
| Expect.equals(505, c.getP()); | |
| } | |
| } | |
| // Generic class inheritance with partial type arguments | |
| class Base<T, U> { | |
| T t; | |
| U u; | |
| Base(this.t, this.u); | |
| } | |
| class Derived<V> extends Base<V, int> { | |
| V v; | |
| Derived(V v_in, int i) : v = v_in, super(v_in, i); | |
| } | |
| // Initializer captures parameter (via closure) | |
| class InitCapture { | |
| final int Function() getP; | |
| InitCapture(int p) : getP = (() => p); | |
| } | |
| // Body captures parameter (via closure) | |
| class BodyCapture { | |
| late final int Function() getP; | |
| BodyCapture(int p) { | |
| getP = () => p; | |
| } | |
| } | |
| class BodyCaptureParamField { | |
| final int p; | |
| late int Function() getP; | |
| BodyCaptureParamField(this.p) { | |
| getP = (() => p); | |
| } | |
| } | |
| class BodyCaptureType<T> { | |
| final int p; | |
| late Type Function() getT; | |
| BodyCaptureType(this.p) { | |
| getT = (() => T); | |
| } | |
| } | |
| // Initializer captures and modifies parameter | |
| class InitCaptureModify { | |
| final int Function() getP; | |
| final int pAfter; | |
| InitCaptureModify(int p) | |
| : getP = (() { | |
| p = p + 1; | |
| return p; | |
| }), | |
| pAfter = (p = p + 2); | |
| } | |
| // Body captures and modifies parameter | |
| class BodyCaptureModify { | |
| late final int Function() getP; | |
| int pInBody = 0; | |
| BodyCaptureModify(int p) { | |
| p = p + 10; | |
| pInBody = p; | |
| getP = () { | |
| p = p + 1; | |
| return p; | |
| }; | |
| } | |
| } | |
| // Initializer stores parameter in field but also modifies it | |
| class InitStoreModify { | |
| int field1; | |
| int field2; | |
| InitStoreModify(int p) : field1 = p, field2 = (p = p + 1); | |
| } | |
| // Constructor body that modifies parameter | |
| class BodyModify { | |
| int field; | |
| int finalP = 0; | |
| BodyModify(int p) : field = p { | |
| p = p + 100; | |
| finalP = p; | |
| } | |
| } | |
| // Super call with modified parameters | |
| class SuperBase { | |
| int x; | |
| SuperBase(this.x); | |
| } | |
| class SuperDerived extends SuperBase { | |
| int y; | |
| SuperDerived(int p) : y = p, super(p = p + 1); | |
| } | |
| // Parameter modified in initializer and then used in body | |
| class ModifyInInitAndUseInBody { | |
| int inInit; | |
| int inBody = 0; | |
| ModifyInInitAndUseInBody(int p) : inInit = (p = p + 1) { | |
| inBody = p; | |
| } | |
| } | |
| // Closure created in initializer captures p, and p is modified in body | |
| class CaptureInInitModifyInBody { | |
| int Function() closure; | |
| int inBody = 0; | |
| CaptureInInitModifyInBody(int p) : closure = (() => p) { | |
| p = p + 10; | |
| inBody = p; | |
| } | |
| } | |
| // Double capture (both in initializer and body) | |
| class DoubleCapture { | |
| int Function() initClosure; | |
| late final int Function() bodyClosure; | |
| DoubleCapture(int p) : initClosure = (() => p) { | |
| p = p + 5; | |
| bodyClosure = () => p; | |
| p = p + 5; | |
| } | |
| } | |
| // Mixed parameters (named, optional) | |
| class MixedParams { | |
| int a; | |
| int b; | |
| int c; | |
| MixedParams(this.a, [this.b = 2, this.c = 3]); | |
| } | |
| class NamedParams { | |
| int a; | |
| int b; | |
| NamedParams({required this.a, this.b = 20}); | |
| } | |
| // Redirecting constructors | |
| class RedirectBase { | |
| int a; | |
| int b; | |
| RedirectBase(this.a, this.b); | |
| RedirectBase.named(int x) : this(x, x + 1); | |
| } | |
| class RedirectDerived extends RedirectBase { | |
| int c; | |
| RedirectDerived(int x, int y) : c = x + y, super.named(x); | |
| } | |
| // Factory constructors | |
| class FactoryClass { | |
| int x; | |
| FactoryClass._(this.x); | |
| factory FactoryClass(int x) => FactoryClass._(x + 100); | |
| } | |
| // Parameter used in multiple initializers and body | |
| class MultiUse { | |
| int a; | |
| int b; | |
| int c = 0; | |
| MultiUse(int p) : a = p, b = (p = p + 1) { | |
| c = p; | |
| } | |
| } | |
| // Parameter captured in initializer and modified in initializer | |
| class CaptureAndModifyInInit { | |
| int Function() getP; | |
| int field; | |
| CaptureAndModifyInInit(int p) : getP = (() => p), field = (p = p + 5); | |
| } |