protected onBeginClass()

in packages/jsii-pacmak/lib/targets/dotnet/dotnetgenerator.ts [325:451]


  protected onBeginClass(cls: spec.ClassType, abstract: boolean) {
    let baseTypeNames: string[] = [];
    const namespace = this.namespaceFor(this.assembly, cls);

    // A class can derive from only one base class
    // But can implement multiple interfaces
    if (!cls.base) {
      baseTypeNames.push('DeputyBase');
    } else {
      const classBase = this.typeresolver.toDotNetType({ fqn: cls.base });
      baseTypeNames.push(classBase);
    }

    if (cls.interfaces && cls.interfaces.length > 0) {
      const implementations =
        this.typeresolver.resolveImplementedInterfaces(cls);
      baseTypeNames = baseTypeNames.concat(implementations);
    }

    const className = this.nameutils.convertClassName(cls);

    // Nested classes will be dealt with during calc code generation
    const nested = this.isNested(cls);
    const absPrefix = abstract ? ' abstract' : '';

    this.openFileIfNeeded(className, namespace, nested);

    const implementsExpr = ` : ${baseTypeNames.join(', ')}`;

    this.dotnetDocGenerator.emitDocs(cls, {
      api: 'type',
      fqn: cls.fqn,
    });

    this.dotnetRuntimeGenerator.emitAttributesForClass(cls);

    this.code.openBlock(
      `public${absPrefix} class ${className}${implementsExpr}`,
    );

    // Compute the class parameters
    let parametersDefinition = '';
    let parametersBase = '';
    const initializer = cls.initializer;
    if (initializer) {
      this.dotnetDocGenerator.emitDocs(initializer, {
        api: 'initializer',
        fqn: cls.fqn,
      });
      this.dotnetRuntimeGenerator.emitDeprecatedAttributeIfNecessary(
        initializer,
      );
      if (initializer.parameters) {
        parametersDefinition = this.renderParametersString(
          initializer.parameters,
        );
        for (const p of initializer.parameters) {
          parametersBase += `${this.nameutils.convertParameterName(p.name)}`;
          // If this is not the last parameter, append ,
          if (
            initializer.parameters.indexOf(p) !==
            initializer.parameters.length - 1
          ) {
            parametersBase += ', ';
          }
        }
      }

      // Create the constructors:
      // Abstract classes have protected constructors.
      const visibility = cls.abstract ? 'protected' : 'public';

      this.code.openBlock(
        `${visibility} ${className}(${parametersDefinition}): base(_MakeDeputyProps(${parametersBase}))`,
      );
      this.code.closeBlock();
      this.code.line();

      // This private method is injected so we can validate arguments before deferring to the base constructor, where
      // the instance will be created in the kernel (where it'd fail on a sub-optimal error instead)...
      this.code.line(
        '[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]',
      );
      this.code.openBlock(
        `private static DeputyProps _MakeDeputyProps(${parametersDefinition})`,
      );
      this.emitUnionParameterValdation(
        (this.reflectAssembly.findType(cls.fqn) as reflect.ClassType)
          .initializer?.parameters,
      );
      const args =
        parametersBase.length > 0
          ? `new object?[]{${parametersBase}}`
          : `System.Array.Empty<object?>()`;
      this.code.line(`return new DeputyProps(${args});`);
      this.code.closeBlock();
      this.code.line();
    }

    this.code.line(
      '/// <summary>Used by jsii to construct an instance of this class from a Javascript-owned object reference</summary>',
    );
    this.code.line(
      '/// <param name="reference">The Javascript-owned object reference</param>',
    );
    this.dotnetRuntimeGenerator.emitDeprecatedAttributeIfNecessary(initializer);
    this.emitHideAttribute();
    this.code.openBlock(
      `protected ${className}(ByRefValue reference): base(reference)`,
    );
    this.code.closeBlock();
    this.code.line();

    this.code.line(
      '/// <summary>Used by jsii to construct an instance of this class from DeputyProps</summary>',
    );
    this.code.line('/// <param name="props">The deputy props</param>');
    this.dotnetRuntimeGenerator.emitDeprecatedAttributeIfNecessary(initializer);
    this.emitHideAttribute();
    this.code.openBlock(
      `protected ${className}(DeputyProps props): base(props)`,
    );
    this.code.closeBlock();

    // We have already outputted members (constructors), setting the flag to true
    this.flagFirstMemberWritten(true);
  }