// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`constructor.js 1`] = `
====================================options=====================================
parsers: ["flow"]
printWidth: 80
                                                                                | printWidth
=====================================input======================================
class A { x: number; }

class B {
  x: number;
  constructor() {
    this.x; // OK
  }
}

class C extends A { }

class D extends A {
  y: number;
  constructor() {
    this.y; // error (no super call)
    this.x; // error (no super call)
  }
}

class E extends A {
  y: number;
  constructor() {
    super();
    this.y; // OK
    this.x; // OK
  }
}

function leak(f) {
  f.y; // error
  f.x; // error
}
class F extends A {
  y: number;
  constructor() {
    leak(this); // error (no super call yet)
    super();
    this.y;
    this.x;
  }
}

class G extends A {
  constructor(b) {
    super.x; // error (no super call)
  }
}

class H extends A {
  y: number;
  constructor() {
    if (Math.random() < 0.5)
      super();
    else
      super();
    this.y; // OK
    this.x; // OK
  }
}

class I_ {
  constructor(leaked_this) {
    leaked_this.foo()
  }
  foo() { }
}
class I extends I_ {
  constructor() {
    super(this); // error (no super call yet)
  }
}

class J__ { }
class J_ extends J__ {
  constructor(closure_leaking_this) {
    closure_leaking_this();
    super();
  }
  foo() { }
}
class J extends J_ {
  constructor() {
    super(() => this.foo()); // error (no super call yet)
    // The reason for this error is that super constructor could call the
    // closure and therefore access this before calling its own super
    // constructor (as shown above). The only safe thing to do in the super
    // constructor is to save the closure so that it can be called later, after
    // initialization is done (as shown below).
  }
}

class K_ {
  closure_leaking_this: () => void;
  constructor(closure_leaking_this) {
    this.closure_leaking_this = closure_leaking_this;
  }
  foo() { }
}
class K extends K_ {
  constructor() {
    super(() => { if (_this) _this.foo() }); // OK
    var _this = this;
    this.closure_leaking_this();
  }
}

// even though super() calls the parent's constructor(), it does not do the same
// conversion on non-objects. so \`new L_()\` returns an instance of \`L_\` because
// the constructor returns false (a non-object), but \`super()\` returns false,
// which then similarly causes \`new L()\` to return an instance of \`L\`.
class L_ {
  constructor() {
    return false;
  }
}
class L extends L_ {
  constructor() {
    let x: boolean = super();
    return x;
  }
}
(new L_(): L_);
(new L(): L);

// similarly, the converse is true: if the parent's constructor returns an
// object, then the child does too.
class M_ {
  constructor() {
    return {foo: 'foo'};
  }
}
class M extends M_ {
  constructor() {
    return super();
  }
}
(new M_(): {foo: string});
(new M(): {foo: string});

// however! super() calls the parent constructor with the subclass as its \`this\`
// value (essentially \`super.constructor.call(this)\`).
class N_ {
  constructor(): this {
    let x = this;
    return x;
  }
}
class N extends N_ {
  constructor() {
    return super();
  }
}
(new N_(): N_);
(new N(): N);

=====================================output=====================================
class A {
  x: number;
}

class B {
  x: number;
  constructor() {
    this.x; // OK
  }
}

class C extends A {}

class D extends A {
  y: number;
  constructor() {
    this.y; // error (no super call)
    this.x; // error (no super call)
  }
}

class E extends A {
  y: number;
  constructor() {
    super();
    this.y; // OK
    this.x; // OK
  }
}

function leak(f) {
  f.y; // error
  f.x; // error
}
class F extends A {
  y: number;
  constructor() {
    leak(this); // error (no super call yet)
    super();
    this.y;
    this.x;
  }
}

class G extends A {
  constructor(b) {
    super.x; // error (no super call)
  }
}

class H extends A {
  y: number;
  constructor() {
    if (Math.random() < 0.5) super();
    else super();
    this.y; // OK
    this.x; // OK
  }
}

class I_ {
  constructor(leaked_this) {
    leaked_this.foo();
  }
  foo() {}
}
class I extends I_ {
  constructor() {
    super(this); // error (no super call yet)
  }
}

class J__ {}
class J_ extends J__ {
  constructor(closure_leaking_this) {
    closure_leaking_this();
    super();
  }
  foo() {}
}
class J extends J_ {
  constructor() {
    super(() => this.foo()); // error (no super call yet)
    // The reason for this error is that super constructor could call the
    // closure and therefore access this before calling its own super
    // constructor (as shown above). The only safe thing to do in the super
    // constructor is to save the closure so that it can be called later, after
    // initialization is done (as shown below).
  }
}

class K_ {
  closure_leaking_this: () => void;
  constructor(closure_leaking_this) {
    this.closure_leaking_this = closure_leaking_this;
  }
  foo() {}
}
class K extends K_ {
  constructor() {
    super(() => {
      if (_this) _this.foo();
    }); // OK
    var _this = this;
    this.closure_leaking_this();
  }
}

// even though super() calls the parent's constructor(), it does not do the same
// conversion on non-objects. so \`new L_()\` returns an instance of \`L_\` because
// the constructor returns false (a non-object), but \`super()\` returns false,
// which then similarly causes \`new L()\` to return an instance of \`L\`.
class L_ {
  constructor() {
    return false;
  }
}
class L extends L_ {
  constructor() {
    let x: boolean = super();
    return x;
  }
}
(new L_(): L_);
(new L(): L);

// similarly, the converse is true: if the parent's constructor returns an
// object, then the child does too.
class M_ {
  constructor() {
    return { foo: "foo" };
  }
}
class M extends M_ {
  constructor() {
    return super();
  }
}
(new M_(): { foo: string });
(new M(): { foo: string });

// however! super() calls the parent constructor with the subclass as its \`this\`
// value (essentially \`super.constructor.call(this)\`).
class N_ {
  constructor(): this {
    let x = this;
    return x;
  }
}
class N extends N_ {
  constructor() {
    return super();
  }
}
(new N_(): N_);
(new N(): N);

================================================================================
`;

exports[`import.js 1`] = `
====================================options=====================================
parsers: ["flow"]
printWidth: 80
                                                                                | printWidth
=====================================input======================================
class D {
  foo(): number { return 0; }
}
module.exports = D;

=====================================output=====================================
class D {
  foo(): number {
    return 0;
  }
}
module.exports = D;

================================================================================
`;

exports[`super.js 1`] = `
====================================options=====================================
parsers: ["flow"]
printWidth: 80
                                                                                | printWidth
=====================================input======================================

class A {
  constructor(x:number) { }
  static staticMethod(x:string): string { return x; }
  f(x:string) { }
}

class B extends A {
  constructor(x:string,y:number) {
    super(x);
  }

  static anotherStatic() {
    (super.staticMethod('foo'): number); // error, string !~> number
    (super.doesntExist()); // error, A doesn't have a doesntExist method
  }

  g() {
    super.f(0);
    return super.g;
  }
}

=====================================output=====================================
class A {
  constructor(x: number) {}
  static staticMethod(x: string): string {
    return x;
  }
  f(x: string) {}
}

class B extends A {
  constructor(x: string, y: number) {
    super(x);
  }

  static anotherStatic() {
    (super.staticMethod("foo"): number); // error, string !~> number
    super.doesntExist(); // error, A doesn't have a doesntExist method
  }

  g() {
    super.f(0);
    return super.g;
  }
}

================================================================================
`;

exports[`test.js 1`] = `
====================================options=====================================
parsers: ["flow"]
printWidth: 80
                                                                                | printWidth
=====================================input======================================
var D = require('./import');
class C extends D {
  constructor() { return super(); }
  foo() { return super.foo(); }
}
module.exports = C;

=====================================output=====================================
var D = require("./import");
class C extends D {
  constructor() {
    return super();
  }
  foo() {
    return super.foo();
  }
}
module.exports = C;

================================================================================
`;
