|
9 | 9 | import { execFile } from "child_process"; |
10 | 10 | import fs from "fs/promises"; |
11 | 11 | import path from "path"; |
| 12 | +import { fileURLToPath } from "url"; |
12 | 13 | import { promisify } from "util"; |
13 | 14 | import type { JSONSchema7 } from "json-schema"; |
14 | 15 | import { |
@@ -38,12 +39,14 @@ import { |
38 | 39 | isObjectSchema, |
39 | 40 | isVoidSchema, |
40 | 41 | getNullableInner, |
| 42 | + getEnumValueDescriptions, |
41 | 43 | getSessionEventVariantSchemas, |
42 | 44 | getSharedSessionEventEnvelopeProperties, |
43 | 45 | rewriteSharedDefinitionReferences, |
44 | 46 | REPO_ROOT, |
45 | 47 | type ApiSchema, |
46 | 48 | type DefinitionCollections, |
| 49 | + type EnumValueDescriptions, |
47 | 50 | type RpcMethod, |
48 | 51 | type SessionEventEnvelopeProperty, |
49 | 52 | } from "./utils.js"; |
@@ -202,6 +205,12 @@ function xmlDocEnumComment(description: string | undefined, indent: string): str |
202 | 205 | return rawXmlDocSummary(`Defines the allowed values.`, indent); |
203 | 206 | } |
204 | 207 |
|
| 208 | +function xmlDocEnumMemberComment(enumValueDescriptions: EnumValueDescriptions | undefined, value: string): string[] { |
| 209 | + const description = enumValueDescriptions?.[value]; |
| 210 | + if (description) return xmlDocComment(description, " "); |
| 211 | + return rawXmlDocSummary(`Gets the <c>${escapeXml(value)}</c> value.`, " "); |
| 212 | +} |
| 213 | + |
205 | 214 | function toPascalCase(name: string): string { |
206 | 215 | const parts = splitCSharpIdentifierParts(name); |
207 | 216 | if (parts.length > 1) return parts.map(toPascalCasePart).join(""); |
@@ -500,6 +509,7 @@ function getOrCreateEnum( |
500 | 509 | values: string[], |
501 | 510 | enumOutput: string[], |
502 | 511 | description?: string, |
| 512 | + enumValueDescriptions?: EnumValueDescriptions, |
503 | 513 | explicitName?: string, |
504 | 514 | deprecated?: boolean, |
505 | 515 | experimental?: boolean |
@@ -531,7 +541,7 @@ function getOrCreateEnum( |
531 | 541 | const usedMemberNames = new Set(STRING_ENUM_RESERVED_MEMBER_NAMES); |
532 | 542 | for (const value of values) { |
533 | 543 | const memberName = uniqueCSharpIdentifier(value, usedMemberNames, "Value"); |
534 | | - lines.push(` /// <summary>Gets the <c>${escapeXml(value)}</c> value.</summary>`); |
| 544 | + lines.push(...xmlDocEnumMemberComment(enumValueDescriptions, value)); |
535 | 545 | lines.push(` public static ${enumName} ${memberName} { get; } = new("${escapeCSharpStringLiteral(value)}");`, ""); |
536 | 546 | } |
537 | 547 | lines.push(` /// <summary>Returns a value indicating whether two <see cref="${enumName}"/> instances are equivalent.</summary>`); |
@@ -1087,7 +1097,7 @@ function resolveSessionPropertyType( |
1087 | 1097 | } |
1088 | 1098 |
|
1089 | 1099 | if (refSchema.enum && Array.isArray(refSchema.enum)) { |
1090 | | - const enumName = getOrCreateEnum(className, "", refSchema.enum as string[], enumOutput, refSchema.description, undefined, isSchemaDeprecated(refSchema), isSchemaExperimental(refSchema)); |
| 1100 | + const enumName = getOrCreateEnum(className, "", refSchema.enum as string[], enumOutput, refSchema.description, getEnumValueDescriptions(refSchema), undefined, isSchemaDeprecated(refSchema), isSchemaExperimental(refSchema)); |
1091 | 1101 | return isRequired ? enumName : `${enumName}?`; |
1092 | 1102 | } |
1093 | 1103 |
|
@@ -1136,7 +1146,7 @@ function resolveSessionPropertyType( |
1136 | 1146 | return !isRequired ? "object?" : "object"; |
1137 | 1147 | } |
1138 | 1148 | if (propSchema.enum && Array.isArray(propSchema.enum)) { |
1139 | | - const enumName = getOrCreateEnum(parentClassName, propName, propSchema.enum as string[], enumOutput, propSchema.description, propSchema.title as string | undefined, isSchemaDeprecated(propSchema), isSchemaExperimental(propSchema)); |
| 1149 | + const enumName = getOrCreateEnum(parentClassName, propName, propSchema.enum as string[], enumOutput, propSchema.description, getEnumValueDescriptions(propSchema), propSchema.title as string | undefined, isSchemaDeprecated(propSchema), isSchemaExperimental(propSchema)); |
1140 | 1150 | return isRequired ? enumName : `${enumName}?`; |
1141 | 1151 | } |
1142 | 1152 | if (propSchema.type === "object" && propSchema.properties) { |
@@ -1240,7 +1250,7 @@ function emitSessionEventEnvelopeProperty( |
1240 | 1250 | return lines; |
1241 | 1251 | } |
1242 | 1252 |
|
1243 | | -function generateSessionEventsCode(schema: JSONSchema7): string { |
| 1253 | +export function generateSessionEventsCode(schema: JSONSchema7): string { |
1244 | 1254 | generatedEnums.clear(); |
1245 | 1255 | sessionDefinitions = collectDefinitionCollections(schema as Record<string, unknown>); |
1246 | 1256 | const variants = extractEventVariants(schema); |
@@ -1438,7 +1448,7 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam |
1438 | 1448 | } |
1439 | 1449 |
|
1440 | 1450 | if (refSchema.enum && Array.isArray(refSchema.enum)) { |
1441 | | - const enumName = getOrCreateEnum(typeName, "", refSchema.enum as string[], rpcEnumOutput, refSchema.description, undefined, isSchemaDeprecated(refSchema), isSchemaExperimental(refSchema) || experimentalRpcTypes.has(typeName)); |
| 1451 | + const enumName = getOrCreateEnum(typeName, "", refSchema.enum as string[], rpcEnumOutput, refSchema.description, getEnumValueDescriptions(refSchema), undefined, isSchemaDeprecated(refSchema), isSchemaExperimental(refSchema) || experimentalRpcTypes.has(typeName)); |
1442 | 1452 | return isRequired ? enumName : `${enumName}?`; |
1443 | 1453 | } |
1444 | 1454 |
|
@@ -1499,6 +1509,7 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam |
1499 | 1509 | schema.enum as string[], |
1500 | 1510 | rpcEnumOutput, |
1501 | 1511 | schema.description, |
| 1512 | + getEnumValueDescriptions(schema), |
1502 | 1513 | explicitName, |
1503 | 1514 | isSchemaDeprecated(schema), |
1504 | 1515 | isSchemaExperimental(schema) || experimentalRpcTypes.has(generatedEnumName), |
@@ -2320,9 +2331,13 @@ async function generate(sessionSchemaPath?: string, apiSchemaPath?: string): Pro |
2320 | 2331 | } |
2321 | 2332 | } |
2322 | 2333 |
|
2323 | | -const sessionArg = process.argv[2] || undefined; |
2324 | | -const apiArg = process.argv[3] || undefined; |
2325 | | -generate(sessionArg, apiArg).catch((err) => { |
2326 | | - console.error("C# generation failed:", err); |
2327 | | - process.exit(1); |
2328 | | -}); |
| 2334 | +const __filename = fileURLToPath(import.meta.url); |
| 2335 | + |
| 2336 | +if (process.argv[1] && path.resolve(process.argv[1]) === __filename) { |
| 2337 | + const sessionArg = process.argv[2] || undefined; |
| 2338 | + const apiArg = process.argv[3] || undefined; |
| 2339 | + generate(sessionArg, apiArg).catch((err) => { |
| 2340 | + console.error("C# generation failed:", err); |
| 2341 | + process.exit(1); |
| 2342 | + }); |
| 2343 | +} |
0 commit comments