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

// test w/ `dart test -N void_checks`

// @dart=2.9

// ignore_for_file: unused_local_variable

import 'dart:async';

Never fail() { throw 'nope'; }
void foo(FutureOr<void> Function() f2) {}

/// https://github.com/dart-lang/linter/issues/2685
void m3() {
  foo(() {
    fail(); // OK
  });

  var f = Future.value(0);
  f.then<void>((_) {
    fail(); // OK
  });
}

void m2() {
  // https://github.com/dart-lang/linter/issues/2794
  Future<void> f = Future.value(1).then<void>((_) { // OK
    throw 'sad';
  });
}

void foo2(FutureOr<void> x) {}

void main() {
  FutureOr<void> x;
  // https://github.com/dart-lang/linter/issues/1675
  foo(x); // OK
}

var x;
get g => null;
set s(v) {}
m() {}

class A<T> {
  T value;
  A();
  A.c(this.value);
  void m1(T arg) {}
  void m2(i, [T v]) {}
  void m3(i, {T v}) {}
  void m4(void arg) {}
  T m5(e) => null;
}

void call_constructor_with_void_positional_parameter() {
  new A<void>.c(x); // LINT
}

void call_method_with_void_positional_parameter() {
  final a = new A<void>();
  a.m1(x); // LINT
}

void call_method_with_void_optional_positional_parameter() {
  final a = new A<void>();
  a.m2(
    null,
    x, // LINT
  );
}

void call_method_with_void_optional_named_parameter() {
  final a = new A<void>();
  a.m3(
    null,
    v: x, // LINT
  );
}

void use_setter_with_void_parameter() {
  final a = new A<void>();
  a.value = x; // LINT
}

void call_method_with_futureOr_void_parameter() {
  final a = new A<FutureOr<void>>();
  // it's OK to pass Future or FutureOr to m1
  a.m1(new Future.value()); // OK
  FutureOr<void> fo;
  a.m1(fo); // OK
  a.m1(x); // OK
  a.m1(null); // OK
  a.m1(1); // LINT
}

void use_setter_with_futureOr_void_parameter() {
  final a = new A<FutureOr<void>>();
  // it's OK to pass Future or FutureOr to set value
  a.value = new Future.value(); //OK
  FutureOr<void> fo;
  a.value = fo; // OK
  a.value = x; // OK
  a.value = null; // OK
  a.value = 1; // LINT
}

void return_inside_block_function_body() {
  return x; // LINT
}

void simple_return_inside_block_function_body() {
  return; // OK
}

void return_from_expression_function_body() => x; // OK

FutureOr<void> return_value_for_futureOr() {
  return 1; // LINT
}

FutureOr<void> return_future_for_futureOr() {
  return new Future.value(); // OK
}

FutureOr<void> return_futureOr_for_futureOr() {
  return x; // OK
}

void assert_is_void_function_is_ok() {
  assert(() {
    return true; // OK
  }());
}

async_function() {
  void f(Function f) {}
  f(() //OK
      async {
    return 1; // OK
  });
}

inference() {
  f(void Function() f) {}
  f(() // LINT
      {
    return 1; // OK
  });
}

generics_with_function() {
  f<T>(T Function() f) => f();
  f(() // OK
      {
    return 1;
  });
  f<void>(() // LINT
      {
    return 1;
  });
}

/// function ref are similar to expression function body with void return type
function_ref_are_ok() {
  fA(void Function(dynamic) f) {}
  fB({void Function(dynamic) f}) {}

  void Function(String e) f1 = (e) {};
  fA(f1); // OK
  final f2 = (e) {};
  fA(f2); // OK
  final f3 = (e) => 1;
  fA(f3); // OK
  final a1 = new A();
  fA(a1.m5); // OK
  fB(f: a1.m5); // OK
  final a2 = new A<void>();
  fA(a2.m5); // OK
}

allow_functionWithReturnType_forFunctionWithout() {
  takeVoidFn(void Function() f) {}
  void Function() voidFn;

  int nonVoidFn() => 1;

  takeVoidFn(nonVoidFn); // OK
  voidFn = nonVoidFn; // OK
  void Function() returnsVoidFn() {
    return nonVoidFn; // OK
  }
  returnsVoidFn();
}

allow_functionWithReturnType_forFunctionWithout_asComplexExpr() {
  takeVoidFn(void Function() f) {}
  void Function() voidFn;

  List<int Function()> listNonVoidFn;

  takeVoidFn(listNonVoidFn[0]); // OK
  voidFn = listNonVoidFn[0]; // OK
  void Function() returnsVoidFn() {
    return listNonVoidFn[0]; // OK
  }
  returnsVoidFn();
}

allow_Null_for_void() {
  forget(void Function() f) {}

  forget(() {}); // OK

  void Function() f;
  f = () {}; // OK
}

allow_Future_void_for_void() {
  forget(void Function() f) {}

  forget(() async {}); // OK

  void Function() f;
  f = () async {}; // OK
}

allow_expression_function_body() {
  forget(void Function() f) {}
  int i;
  forget(() => i); // OK
  forget(() => i++); // OK

  void Function() f;
  f = () => i; // OK
  f = () => i++; // OK
}

void emptyFunctionExpressionReturningFutureOrVoid(FutureOr<void> Function() f) {
  f = () {}; // OK
}
