private _addToSubmodule()

in src/assembler.ts [708:770]


  private _addToSubmodule(ns: ts.Symbol, moduleLike: ts.Symbol, packageRoot: string) {
    // For each symbol exported by the moduleLike, map it to the ns submodule.
    for (const symbol of this._typeChecker.getExportsOfModule(moduleLike)) {
      if (this._submoduleMap.has(symbol)) {
        const currNs = this._submoduleMap.get(symbol)!;
        // Checking if there's been two submodules exporting the same symbol,
        // which is illegal. We can tell if the currently registered symbol has
        // a different name than the one we're currently trying to register in.
        if (currNs.name !== ns.name) {
          const currNsDecl = currNs.valueDeclaration ?? currNs.declarations?.[0];
          const nsDecl = ns.valueDeclaration ?? ns.declarations?.[0];

          // Make sure the error message always lists causes in the same order
          const refs = [
            { decl: currNsDecl, name: currNs.name } as const,
            { decl: nsDecl, name: ns.name } as const,
          ].sort(({ name: l }, { name: r }) => l.localeCompare(r));

          this._diagnostics.push(
            JsiiDiagnostic.JSII_3003_SYMBOL_IS_EXPORTED_TWICE.create(
              _nameOrDeclarationNode(symbol),
              refs[0].name,
              refs[1].name,
            )
              .addRelatedInformationIf(refs[0].decl, `Symbol is exported under the "${refs[0].name}" submodule`)
              .addRelatedInformationIf(refs[1].decl, `Symbol is exported under the "${refs[1].name}" submodule`),
          );
        }
        // Found two re-exports, which is odd, but they use the same submodule,
        // so it's probably okay? That's likely a tsc error, which will have
        // been reported for us already anyway.
        continue;
      }
      this._submoduleMap.set(symbol, ns);

      // If the exported symbol has any declaration, and that delcaration is of
      // an entity that can have nested declarations of interest to jsii
      // (classes, interfaces, enums, modules), we need to also associate those
      // nested symbols to the submodule (or they won't be named correctly!)
      const decl = symbol.declarations?.[0];
      if (decl != null) {
        if (ts.isClassDeclaration(decl) || ts.isInterfaceDeclaration(decl) || ts.isEnumDeclaration(decl)) {
          const type = this._typeChecker.getTypeAtLocation(decl);
          if (isSingleValuedEnum(type, this._typeChecker)) {
            // type.symbol !== symbol, because symbol is the enum itself, but
            // since it's single-valued, the TypeChecker will only show us the
            // value's symbol later on.
            this._submoduleMap.set(type.symbol, ns);
          }
          if (type.symbol.exports) {
            // eslint-disable-next-line no-await-in-loop
            this._addToSubmodule(ns, symbol, packageRoot);
          }
        } else if (ts.isModuleDeclaration(decl)) {
          // eslint-disable-next-line no-await-in-loop
          this._registerNamespaces(symbol, packageRoot);
        } else if (ts.isNamespaceExport(decl)) {
          // eslint-disable-next-line no-await-in-loop
          this._registerNamespaces(symbol, packageRoot);
        }
      }
    }
  }