private emitMethod()

in packages/jsii-pacmak/lib/targets/dotnet/dotnetgenerator.ts [567:653]


  private emitMethod(
    cls: spec.ClassType | spec.InterfaceType,
    method: spec.Method,
    definingType: spec.Type,
    emitForProxyOrDatatype = false,
  ): void {
    this.emitNewLineIfNecessary();
    const returnType = method.returns
      ? this.typeresolver.toDotNetType(method.returns.type)
      : 'void';
    const staticKeyWord = method.static ? 'static ' : '';
    let overrideKeyWord = '';
    let virtualKeyWord = '';

    let definedOnAncestor = false;
    // In the case of the source being a class, we check if it is already defined on an ancestor
    if (spec.isClassType(cls)) {
      definedOnAncestor = this.isMemberDefinedOnAncestor(cls, method);
    }
    // The method is an override if it's defined on the ancestor, or if the parent is a class and we are generating a proxy or datatype class
    let overrides =
      definedOnAncestor || (spec.isClassType(cls) && emitForProxyOrDatatype);
    // We also inspect the jsii model to see if it overrides a class member.
    if (method.overrides) {
      const overrideType = this.findType(method.overrides);
      if (spec.isClassType(overrideType)) {
        // Overrides a class, needs overrides keyword
        overrides = true;
      }
    }
    if (overrides) {
      // Add the override key word if the method is emitted for a proxy or data type or is defined on an ancestor. If
      // the member is static, use the "new" keyword instead, to indicate we are intentionally hiding the ancestor
      // declaration (as C# does not inherit statics, they can be hidden but not overridden). The "new" keyword is
      // optional in this context, but helps clarify intention.
      overrideKeyWord = method.static ? 'new ' : 'override ';
    } else if (
      !method.static &&
      (method.abstract || !definedOnAncestor) &&
      !emitForProxyOrDatatype
    ) {
      // Add the virtual key word if the method is abstract or not defined on an ancestor and we are NOT generating a proxy or datatype class
      // Methods should always be virtual when possible
      virtualKeyWord = 'virtual ';
    }

    const access = this.renderAccessLevel(method);
    const methodName = this.nameutils.convertMethodName(method.name);

    const isOptional = method.returns && method.returns.optional ? '?' : '';
    const signature = `${returnType}${isOptional} ${methodName}(${this.renderMethodParameters(
      method,
    )})`;

    this.dotnetDocGenerator.emitDocs(method, {
      api: 'member',
      fqn: definingType.fqn,
      memberName: method.name,
    });
    this.dotnetRuntimeGenerator.emitAttributesForMethod(
      cls,
      method /*, emitForProxyOrDatatype*/,
    );

    if (method.abstract) {
      this.code.line(`${access} ${overrideKeyWord}abstract ${signature};`);
      this.code.line();
    } else {
      this.code.openBlock(
        `${access} ${staticKeyWord}${overrideKeyWord}${virtualKeyWord}${signature}`,
      );
      this.emitUnionParameterValdation(
        (
          this.reflectAssembly.findType(cls.fqn) as
            | reflect.ClassType
            | reflect.InterfaceType
        ).allMethods.find((m) => m.name === method.name)!.parameters,
      );
      this.code.line(
        this.dotnetRuntimeGenerator.createInvokeMethodIdentifier(
          method,
          cls as spec.ClassType,
        ),
      );
      this.code.closeBlock();
    }
  }