private _visitProperty()

in src/assembler.ts [1967:2084]


  private _visitProperty(
    symbol: ts.Symbol,
    type: spec.ClassType | spec.InterfaceType,
    ctx: EmitContext,
    declaringTypeDecl: ts.ClassLikeDeclaration | ts.InterfaceDeclaration | undefined,
  ) {
    if (type.properties?.find((p) => p.name === symbol.name)) {
      /*
       * Second declaration of the same property. For example, if code specifies a getter & setter signature,
       * there will be one pass for each of the signatures, but we can process only the first encountered. The
       * typescript compiler will take care of making sure we don't have conflicting declarations, anyway.
       */
      return;
    }

    if (LOG.isTraceEnabled()) {
      LOG.trace(`Processing property: ${chalk.green(type.fqn)}#${chalk.cyan(symbol.name)}`);
    }

    const declaration = symbol.valueDeclaration ?? symbol.declarations?.[0];
    const signature = declaration as
      | ts.PropertySignature
      | ts.PropertyDeclaration
      | ts.AccessorDeclaration
      | ts.ParameterPropertyDeclaration;

    if (type.name === Case.pascal(symbol.name)) {
      this._diagnostics.push(
        JsiiDiagnostic.JSII_5019_MEMBER_TYPE_NAME_CONFLICT.create(
          signature.name,
          'property',
          symbol,
          type,
        ).addRelatedInformationIf(
          declaringTypeDecl?.name ?? declaringTypeDecl,
          `The declaring ${type.kind} is introduced here`,
        ),
      );
    }

    if (isProhibitedMemberName(symbol.name)) {
      this._diagnostics.push(
        JsiiDiagnostic.JSII_5016_PROHIBITED_MEMBER_NAME.create(
          symbol.valueDeclaration ?? symbol.declarations?.[0],
          symbol.name,
        ),
      );
      return;
    }

    this._warnAboutReservedWords(symbol);

    const property: spec.Property = bindings.setPropertyRelatedNode(
      {
        ...this._optionalValue(
          this._typeChecker.getTypeOfSymbolAtLocation(symbol, signature),
          signature.type ?? signature.name,
          'property type',
        ),
        abstract: _isAbstract(symbol, type) || undefined,
        name: symbol.name,
        protected: _isProtected(symbol) || undefined,
        static: _isStatic(symbol) || undefined,
        locationInModule: this.declarationLocation(signature),
      },
      signature,
    );

    if (ts.isGetAccessor(signature)) {
      property.immutable = true;
      for (const decl of symbol.getDeclarations() ?? []) {
        if (!ts.isSetAccessor(decl)) {
          continue;
        }
        delete property.immutable;

        // Verify the setter doesn't have a Separate Write Type (SWT)
        const valueParam = decl.parameters[0];
        if (valueParam?.type == null) {
          // If there is no type node, there can't be a SWT
          continue;
        }
        const paramType = this._typeChecker.getTypeFromTypeNode(valueParam.type);
        const paramOptionalValue = this._optionalValue(paramType, valueParam.type, 'parameter type');

        if (
          property.optional !== paramOptionalValue.optional ||
          describeTypeReference(property.type) !== describeTypeReference(paramOptionalValue.type)
        ) {
          this._diagnostics.push(
            JsiiDiagnostic.JSII_1005_SEPARATE_WRITE_TYPE.create(valueParam.type).addRelatedInformation(
              signature.type ?? signature.name,
              'The getter signature is declared here',
            ),
          );
        }
      }
    } else {
      property.immutable = (ts.getCombinedModifierFlags(signature) & ts.ModifierFlags.Readonly) !== 0 || undefined;
    }

    if (signature.questionToken) {
      property.optional = true;
    }

    if (property.static && property.immutable && ts.isPropertyDeclaration(signature) && signature.initializer) {
      property.const = true;
    }

    property.docs = this._visitDocumentation(symbol, ctx).docs;

    type.properties = type.properties ?? [];
    if (type.properties.find((prop) => prop.name === property.name && prop.static === property.static) != null) {
      LOG.trace(`Dropping re-declaration of ${chalk.green(type.fqn)}#${chalk.cyan(property.name)}`);
      return;
    }
    type.properties.push(property);
  }