// Copyright (c) 2012, 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.9

import "package:expect/expect.dart";

class ParameterInitializerTest {
  static testMain() {
    var obj = new Foo.untyped(1);
    Expect.equals(1, obj.x);

    obj = new Foo.subtype(7);
    Expect.equals(7, obj.x);

    obj = new Foo.optional(111);
    Expect.equals(111, obj.x);

    obj = new Foo.optional();
    Expect.equals(5, obj.x);

    obj = new Foo(1);
    Expect.equals(2, obj.x);

    obj = new SubFoo(42);
    Expect.equals(1, obj.x);

    obj = new SubSubFoo(42);
    Expect.equals(1, obj.x);
  }
}

class Foo {
  Foo(num this.x) {
    // Reference to x must resolve to the field.
    x++;
    Expect.equals(this.x, x);
  }

  Foo.untyped(this.x) {}
  Foo.subtype(int this.x) {}
  Foo.optional([this.x = 5]) {}

  num x;
}

class SubFoo extends Foo {
  SubFoo(num y)
      : x_ = 0,
        super(y) {
    // Subfoo.setter of x has been invoked in the Foo constructor.
    Expect.equals(x, 1);
    Expect.equals(x_, 1);

    // The super.x will resolved to the field in Foo.
    Expect.equals(super.x, y);
  }

  get x {
    return x_;
  }

  set x(num val) {
    x_ = val;
  }

  num x_;
}

class SubSubFoo extends SubFoo {
  SubSubFoo(num y) : super(y) {
    // Subfoo.setter of x has been invoked in the Foo constructor.
    Expect.equals(x, 1);
    Expect.equals(x_, 1);

    // There is no way to get to the field in Foo.
    Expect.equals(super.x, 1);
  }
}

main() {
  ParameterInitializerTest.testMain();
}
