private resolve()

in packages/jsii-pacmak/lib/targets/python/type-name.ts [295:403]


  private resolve({
    assembly,
    emittedTypes,
    submodule,
    surroundingTypeFqns,
    typeAnnotation = true,
    parameterType,
    typeResolver,
  }: NamingContext) {
    const { assemblyName, packageName, pythonFqn } = toPythonFqn(
      this.#fqn,
      assembly,
    );

    // If this is a type annotation for a parameter, allow dicts to be passed where structs are expected.
    const type = typeResolver(this.#fqn);
    const isStruct = isInterfaceType(type) && !!type.datatype;
    const wrapType =
      typeAnnotation && parameterType && isStruct
        ? (pyType: string) =>
            `typing.Union[${pyType}, typing.Dict[builtins.str, typing.Any]]`
        : (pyType: string) => pyType;

    // Emit aliased imports for dependencies (this avoids name collisions)
    if (assemblyName !== assembly.name) {
      const aliasSuffix = createHash('sha256')
        .update(assemblyName)
        .update('.*')
        .digest('hex')
        .substring(0, 8);
      const alias = `_${packageName.replace(/\./g, '_')}_${aliasSuffix}`;

      const aliasedFqn = `${alias}${pythonFqn.slice(packageName.length)}`;

      return {
        // If it's a struct, then we allow passing as a dict, too...
        pythonType: wrapType(aliasedFqn),
        requiredImport: {
          sourcePackage: `${packageName} as ${alias}`,
          item: '',
        },
      };
    }

    const submodulePythonName = toPythonFqn(submodule, assembly).pythonFqn;
    const typeSubmodulePythonName = toPythonFqn(
      findParentSubmodule(type, assembly),
      assembly,
    ).pythonFqn;

    if (typeSubmodulePythonName === submodulePythonName) {
      // Identify declarations that are not yet initialized and hence cannot be
      // used as part of a type qualification. Since this is not a forward
      // reference, the type was already emitted and its un-qualified name must
      // be used instead of its locally qualified name.
      const nestingParent = surroundingTypeFqns
        ?.map((fqn) => toPythonFqn(fqn, assembly).pythonFqn)
        ?.reverse()
        ?.find((parent) => pythonFqn.startsWith(`${parent}.`));

      if (
        typeAnnotation &&
        (!emittedTypes.has(this.#fqn) || nestingParent != null)
      ) {
        // Possibly a forward reference, outputting the stringifierd python FQN
        return {
          pythonType: wrapType(
            JSON.stringify(pythonFqn.substring(submodulePythonName.length + 1)),
          ),
        };
      }

      if (!typeAnnotation && nestingParent) {
        // This is not for a type annotation, so we should be at a point in time
        // where the surrounding symbol has been defined entirely, so we can
        // refer to it "normally" now.
        return { pythonType: pythonFqn.slice(packageName.length + 1) };
      }

      // We'll just make a module-qualified reference at this point.
      return {
        pythonType: wrapType(
          pythonFqn.substring(submodulePythonName.length + 1),
        ),
      };
    }

    const [toImport, ...nested] = pythonFqn
      .substring(typeSubmodulePythonName.length + 1)
      .split('.');
    const aliasSuffix = createHash('sha256')
      .update(typeSubmodulePythonName)
      .update('.')
      .update(toImport)
      .digest('hex')
      .substring(0, 8);
    const alias = `_${toImport}_${aliasSuffix}`;

    return {
      pythonType: wrapType([alias, ...nested].join('.')),
      requiredImport: {
        sourcePackage: relativeImportPath(
          submodulePythonName,
          typeSubmodulePythonName,
        ),
        item: `${toImport} as ${alias}`,
      },
    };
  }