<commit_before>import 'package:winmd/winmd.dart';

import '../method.dart';
import '../type.dart';
import 'declarations/comobject.dart';
import 'declarations/datetime.dart';
import 'declarations/default.dart';
import 'declarations/duration.dart';
import 'declarations/enum.dart';
import 'declarations/string.dart';
import 'declarations/vector.dart';
import 'declarations/void.dart';
import 'winrt_parameter.dart';

class WinRTMethodProjection extends MethodProjection {
  WinRTMethodProjection(super.method, super.vtableOffset) {
    parameters = method.parameters
        .map((param) => WinRTParameterProjection(
            param.name, TypeProjection(param.typeIdentifier)))
        .toList();
  }

  // MethodProjection overrides

  @override
  String get dartParams => [
        'Pointer',
        ...parameters.map((param) => param.dartProjection),
        if (!isVoidReturn)
          isCOMObjectReturn
              ? 'Pointer<COMObject>'
              : 'Pointer<${returnType.nativeType}>',
      ].join(', ');

  @override
  String get nativeParams => [
        'Pointer',
        ...parameters.map((param) => param.ffiProjection),
        if (!isVoidReturn)
          isCOMObjectReturn
              ? 'Pointer<COMObject>'
              : 'Pointer<${returnType.nativeType}>',
      ].join(', ');

  // WinRT methods always return an HRESULT
  @override
  String get nativePrototype => 'HRESULT Function($nativeParams)';

  // WinRT properties always return an HRESULT
  @override
  String get dartPrototype => 'int Function($dartParams)';

  @override
  String get identifiers => [
        'ptr.ref.lpVtbl',
        ...parameters.map(
            (param) => (param as WinRTParameterProjection).localIdentifier),
        if (!isVoidReturn) 'retValuePtr',
      ].join(', ');

  // Matcher properties

  bool get isBooleanReturn => returnType.dartType == 'bool';

  bool get isEnumReturn => returnType.isWinRTEnum;

  bool get isCOMObjectReturn => returnType.dartType == 'Pointer<COMObject>';

  bool get isVoidReturn => returnType.dartType == 'void';

  bool get isStringReturn => returnType.isString;

  bool get isDateTimeReturn =>
      returnType.typeIdentifier.name == 'Windows.Foundation.DateTime';

  bool get isTimeSpanReturn =>
      returnType.typeIdentifier.name == 'Windows.Foundation.TimeSpan';

  bool get isVectorReturn =>
      returnType.typeIdentifier.baseType == BaseType.genericTypeModifier &&
      (returnType.typeIdentifier.type?.name.endsWith('IVector`1') ?? false);

  bool get isVectorViewReturn =>
      returnType.typeIdentifier.baseType == BaseType.genericTypeModifier &&
      (returnType.typeIdentifier.type?.name.endsWith('IVectorView`1') ?? false);

  String get parametersPreamble => parameters
      .map((param) => (param as WinRTParameterProjection).preamble)
      .join('\n');

  String get parametersPostamble => parameters
      .map((param) => (param as WinRTParameterProjection).postamble)
      .join('\n');

  String ffiCall([String params = '']) => '''
    final hr = ptr.ref.vtable
      .elementAt($vtableOffset)
      .cast<Pointer<NativeFunction<$nativePrototype>>>()
      .value
      .asFunction<$dartPrototype>()($identifiers);

    if (FAILED(hr)) throw WindowsException(hr);
  ''';

  /// Returns the method declaration for a method or property declaration class
  /// specified in [creator].
  ///
  /// [creator] must be the constructor of a WinRT method or property
  /// declaration class (e.g. `VectorMethod.new`, `StringGetProperty.new`,
  /// `EnumSetProperty.new`).
  String declarationFor(WinRTMethodProjection Function(Method, int) creator) =>
      creator(method, vtableOffset).toString();

  @override
  String toString() {
    try {
      if (isEnumReturn) {
        return declarationFor(WinRTMethodReturningEnumProjection.new);
      }

      if (isVectorReturn) {
        return declarationFor(WinRTMethodReturningVectorProjection.new);
      }

      if (isVectorViewReturn) {
        return declarationFor(WinRTMethodReturningVectorViewProjection.new);
      }<commit_msg>Update documentation<commit_after>import 'package:winmd/winmd.dart';

import '../method.dart';
import '../type.dart';
import 'declarations/comobject.dart';
import 'declarations/datetime.dart';
import 'declarations/default.dart';
import 'declarations/duration.dart';
import 'declarations/enum.dart';
import 'declarations/string.dart';
import 'declarations/vector.dart';
import 'declarations/void.dart';
import 'winrt_parameter.dart';

class WinRTMethodProjection extends MethodProjection {
  WinRTMethodProjection(super.method, super.vtableOffset) {
    parameters = method.parameters
        .map((param) => WinRTParameterProjection(
            param.name, TypeProjection(param.typeIdentifier)))
        .toList();
  }

  // MethodProjection overrides

  @override
  String get dartParams => [
        'Pointer',
        ...parameters.map((param) => param.dartProjection),
        if (!isVoidReturn)
          isCOMObjectReturn
              ? 'Pointer<COMObject>'
              : 'Pointer<${returnType.nativeType}>',
      ].join(', ');

  @override
  String get nativeParams => [
        'Pointer',
        ...parameters.map((param) => param.ffiProjection),
        if (!isVoidReturn)
          isCOMObjectReturn
              ? 'Pointer<COMObject>'
              : 'Pointer<${returnType.nativeType}>',
      ].join(', ');

  // WinRT methods always return an HRESULT
  @override
  String get nativePrototype => 'HRESULT Function($nativeParams)';

  // WinRT properties always return an HRESULT
  @override
  String get dartPrototype => 'int Function($dartParams)';

  @override
  String get identifiers => [
        'ptr.ref.lpVtbl',
        ...parameters.map(
            (param) => (param as WinRTParameterProjection).localIdentifier),
        if (!isVoidReturn) 'retValuePtr',
      ].join(', ');

  // Matcher properties

  bool get isBooleanReturn => returnType.dartType == 'bool';

  bool get isEnumReturn => returnType.isWinRTEnum;

  bool get isCOMObjectReturn => returnType.dartType == 'Pointer<COMObject>';

  bool get isVoidReturn => returnType.dartType == 'void';

  bool get isStringReturn => returnType.isString;

  bool get isDateTimeReturn =>
      returnType.typeIdentifier.name == 'Windows.Foundation.DateTime';

  bool get isTimeSpanReturn =>
      returnType.typeIdentifier.name == 'Windows.Foundation.TimeSpan';

  bool get isVectorReturn =>
      returnType.typeIdentifier.baseType == BaseType.genericTypeModifier &&
      (returnType.typeIdentifier.type?.name.endsWith('IVector`1') ?? false);

  bool get isVectorViewReturn =>
      returnType.typeIdentifier.baseType == BaseType.genericTypeModifier &&
      (returnType.typeIdentifier.type?.name.endsWith('IVectorView`1') ?? false);

  String get parametersPreamble => parameters
      .map((param) => (param as WinRTParameterProjection).preamble)
      .join('\n');

  String get parametersPostamble => parameters
      .map((param) => (param as WinRTParameterProjection).postamble)
      .join('\n');

  String ffiCall([String params = '']) => '''
    final hr = ptr.ref.vtable
      .elementAt($vtableOffset)
      .cast<Pointer<NativeFunction<$nativePrototype>>>()
      .value
      .asFunction<$dartPrototype>()($identifiers);

    if (FAILED(hr)) throw WindowsException(hr);
  ''';

  /// Returns the method declaration for a method or property declaration class
  /// specified in [creator].
  ///
  /// [creator] must be the constructor of a WinRT method or property
  /// declaration class (e.g. `WinRTMethodReturningVectorProjection.new`,
  /// `WinRTGetPropertyReturningStringProjection.new`,
  /// `WinRTSetPropertyReturningEnumProjection.new`).
  String declarationFor(WinRTMethodProjection Function(Method, int) creator) =>
      creator(method, vtableOffset).toString();

  @override
  String toString() {
    try {
      if (isEnumReturn) {
        return declarationFor(WinRTMethodReturningEnumProjection.new);
      }

      if (isVectorReturn) {
        return declarationFor(WinRTMethodReturningVectorProjection.new);
      }

      if (isVectorViewReturn) {
        return declarationFor(WinRTMethodReturningVectorViewProjection.new);
      }
{'fraction_non_alphanumeric': 0.12794243200390293, 'fraction_numerical': 0.00048786437370411026, 'mean_word_length': 3.451682953311618, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '11932', 'n_tokens_mistral': 2363, 'n_tokens_neox': 2333, 'n_words': 477}