blob: 1d1e4cf11f6e493219b2f50fe5d3f512a954c526 [file] [edit]
// 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);
}