Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/compiler/generators/imports.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import type { CodeGeneratorFileContext } from ".";
import { TS_FILE_ID } from "../constants";
import { getFullClassName, hasNode, lookupNode } from "../node-util";
import {
getFullClassName,
hasNode,
lookupNode,
tryLookupNode,
} from "../node-util";
import * as util from "../util";
import type * as schema from "../../capnp/schema";

Expand Down Expand Up @@ -60,7 +65,11 @@ export function generateNestedImports(ctx: CodeGeneratorFileContext): void {
}
}

const importNode = lookupNode(ctx, imp);
const importNode = tryLookupNode(ctx, imp);
if (!importNode) {
// Skip imports for nodes that aren't available in the current context
continue;
}

const imports = getImportNodes(ctx, importNode)
.flatMap((node) => {
Expand Down
43 changes: 37 additions & 6 deletions src/compiler/node-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ export function getConcreteListType(
if (elementTypeWhich === schema.Type.LIST) {
return `$.PointerList(${getConcreteListType(ctx, elementType)})`;
} else if (elementTypeWhich === schema.Type.STRUCT) {
const structNode = lookupNode(ctx, elementType.struct.typeId);
const structNode = tryLookupNode(ctx, elementType.struct.typeId);

if (
structNode &&
structNode.struct.preferredListEncoding !==
schema.ElementSize.INLINE_COMPOSITE
schema.ElementSize.INLINE_COMPOSITE
) {
throw new Error(E.GEN_FIELD_NON_INLINE_STRUCT_LIST);
}
Expand Down Expand Up @@ -85,7 +86,12 @@ export function getJsType(
}

case schema.Type.ENUM: {
return getFullClassName(lookupNode(ctx, type.enum.typeId));
const node = tryLookupNode(ctx, type.enum.typeId);
if (!node) {
// External enum type - generate a placeholder type name
return `Enum_${type.enum.typeId.toString(16)}`;
}
return getFullClassName(node);
}

case schema.Type.FLOAT32:
Expand All @@ -105,16 +111,26 @@ export function getJsType(
}

case schema.Type.INTERFACE: {
return getFullClassName(lookupNode(ctx, type.interface.typeId));
const node = tryLookupNode(ctx, type.interface.typeId);
if (!node) {
// External interface type - generate a placeholder type name
return `Interface_${type.interface.typeId.toString(16)}`;
}
return getFullClassName(node);
}

case schema.Type.LIST: {
return `$.List${constructor ? "Ctor" : ""}<${getJsType(ctx, type.list.elementType, false)}>`;
}

case schema.Type.STRUCT: {
const c = getFullClassName(lookupNode(ctx, type.struct.typeId));

const node = tryLookupNode(ctx, type.struct.typeId);
if (!node) {
// External struct type - generate a placeholder type name
const c = `Struct_${type.struct.typeId.toString(16)}`;
return constructor ? `$.StructCtor<${c}>` : c;
}
const c = getFullClassName(node);
return constructor ? `$.StructCtor<${c}>` : c;
}

Expand Down Expand Up @@ -196,6 +212,21 @@ export function lookupNode(
return node;
}

/**
* Attempts to look up a Node in the schema by its ID without throwing.
*
* @param ctx - The file context containing all nodes from the schema
* @param lookup - Either a Node ID as a bigint, or an object containing an ID field
* @returns The found Node from the schema, or undefined if not found
*/
export function tryLookupNode(
ctx: CodeGeneratorFileContext,
lookup: { readonly id: bigint } | bigint,
): schema.Node | undefined {
const id = typeof lookup === "bigint" ? lookup : lookup.id;
return ctx.nodes.find((n) => n.id === id);
}

/**
* Looks up source information for a Node in the schema by its ID.
*
Expand Down