// Copyright (c) 2021, 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:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';

extension DartCompletionRequestExtensions on DartCompletionRequest {
  /// Return `true` if the constructor tear-offs feature is enabled, and the
  /// context type is a function type that matches an instantiation of the
  /// [element].
  ///
  // TODO(scheglov): Validate that suggesting a tear-off instead of invocation
  // is statistically a good choice.
  bool shouldSuggestTearOff(InterfaceElement element) {
    if (!libraryElement.featureSet.isEnabled(Feature.constructor_tearoffs)) {
      return false;
    }

    var contextType = this.contextType;
    if (contextType is! FunctionType) {
      return false;
    }

    var bottomInstance = element.instantiate(
      typeArguments: List.filled(
        element.typeParameters.length,
        libraryElement.typeProvider.neverType,
      ),
      nullabilitySuffix: NullabilitySuffix.none,
    );

    return libraryElement.typeSystem.isSubtypeOf(
      bottomInstance,
      contextType.returnType,
    );
  }
}
