From 92931e1931ae50972cc1e537ddf5e93f39edea42 Mon Sep 17 00:00:00 2001 From: Thomas Baker Date: Fri, 17 Oct 2025 14:04:02 -0400 Subject: [PATCH 1/8] fix(php): Fix enum string escaping and reserved keyword handling This commit fixes two critical bugs in the PHP generator: 1. **Enum string escaping**: Enum values containing quotes are now properly escaped - Before: case Foo = "bar[x="y"]"; (syntax error) - After: case Foo = "bar[x=\"y\"]"; (valid PHP) - Fixed in: generators/php/codegen/src/ast/Enum.ts 2. **Reserved keyword handling**: PHP reserved keywords (e.g., "eval", "list") are now prefixed with the root namespace to avoid syntax errors - Before: class Eval { } (syntax error - "eval" is reserved) - After: class VapiEval { } (valid PHP, assuming "Vapi" is root namespace) - Fixed in: - generators/php/base/src/context/AbstractPhpGeneratorContext.ts - generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts These fixes were discovered when generating a PHP SDK for Vapi, which had: - 5 enum files with unescaped quotes causing parse errors - A type named "Eval" which is a PHP reserved keyword Resolves syntax errors in generated PHP code that prevented compilation. --- .../context/AbstractPhpGeneratorContext.ts | 25 ++++++++++++++++++- generators/php/codegen/src/ast/Enum.ts | 4 ++- .../DynamicSnippetsGeneratorContext.ts | 25 ++++++++++++++++++- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/generators/php/base/src/context/AbstractPhpGeneratorContext.ts b/generators/php/base/src/context/AbstractPhpGeneratorContext.ts index d448d1bc675..61b7f947c9f 100644 --- a/generators/php/base/src/context/AbstractPhpGeneratorContext.ts +++ b/generators/php/base/src/context/AbstractPhpGeneratorContext.ts @@ -82,7 +82,30 @@ export abstract class AbstractPhpGeneratorContext< } public getClassName(name: Name): string { - return name.pascalCase.safeName; + const className = name.pascalCase.safeName; + + // PHP reserved keywords (case-insensitive) that cannot be used as class names + // Source: https://www.php.net/manual/en/reserved.keywords.php + const PHP_RESERVED_KEYWORDS = new Set([ + "abstract", "and", "array", "as", "break", "callable", "case", "catch", + "class", "clone", "const", "continue", "declare", "default", "die", "do", + "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", + "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", + "finally", "fn", "for", "foreach", "function", "global", "goto", "if", + "implements", "include", "include_once", "instanceof", "insteadof", + "interface", "isset", "list", "match", "namespace", "new", "or", "print", + "private", "protected", "public", "readonly", "require", "require_once", + "return", "static", "switch", "throw", "trait", "try", "unset", "use", + "var", "while", "xor", "yield", "yield_from", "__halt_compiler" + ]); + + // Check if the class name is a reserved keyword (case-insensitive) + if (PHP_RESERVED_KEYWORDS.has(className.toLowerCase())) { + // Prefix with the root namespace name to avoid collision + return `${this.rootNamespace}${className}`; + } + + return className; } public getGlobalNamespace(): string { diff --git a/generators/php/codegen/src/ast/Enum.ts b/generators/php/codegen/src/ast/Enum.ts index d981c2f5b4c..e52cbc67e32 100644 --- a/generators/php/codegen/src/ast/Enum.ts +++ b/generators/php/codegen/src/ast/Enum.ts @@ -71,7 +71,9 @@ export class Enum extends AstNode { writer.write(`case ${member.name}`); if (member.value != null) { if (typeof member.value === "string") { - writer.write(` = "${member.value}"`); + // Escape backslashes and double quotes in the string value + const escapedValue = member.value.replace(/\\/g, "\\\\").replace(/"/g, '\\"'); + writer.write(` = "${escapedValue}"`); } else { writer.write(` = ${member.value}`); } diff --git a/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts b/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts index 8a0aee306b0..3a56ed88a92 100644 --- a/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts +++ b/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts @@ -63,7 +63,30 @@ export class DynamicSnippetsGeneratorContext extends AbstractDynamicSnippetsGene } public getClassName(name: FernIr.Name): string { - return name.pascalCase.safeName; + const className = name.pascalCase.safeName; + + // PHP reserved keywords (case-insensitive) that cannot be used as class names + // Source: https://www.php.net/manual/en/reserved.keywords.php + const PHP_RESERVED_KEYWORDS = new Set([ + "abstract", "and", "array", "as", "break", "callable", "case", "catch", + "class", "clone", "const", "continue", "declare", "default", "die", "do", + "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", + "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", + "finally", "fn", "for", "foreach", "function", "global", "goto", "if", + "implements", "include", "include_once", "instanceof", "insteadof", + "interface", "isset", "list", "match", "namespace", "new", "or", "print", + "private", "protected", "public", "readonly", "require", "require_once", + "return", "static", "switch", "throw", "trait", "try", "unset", "use", + "var", "while", "xor", "yield", "yield_from", "__halt_compiler" + ]); + + // Check if the class name is a reserved keyword (case-insensitive) + if (PHP_RESERVED_KEYWORDS.has(className.toLowerCase())) { + // Prefix with the root namespace name to avoid collision + return `${this.rootNamespace}${className}`; + } + + return className; } public getRootClientClassName(): string { From fb2acc3599e0194b4dfa8f9d48b3597e5b5d964f Mon Sep 17 00:00:00 2001 From: Thomas Baker Date: Fri, 17 Oct 2025 14:11:29 -0400 Subject: [PATCH 2/8] chore(php): Add versions.yml entry for v1.17.2 --- generators/php/sdk/versions.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/generators/php/sdk/versions.yml b/generators/php/sdk/versions.yml index d9d99c256e9..37983f8e833 100644 --- a/generators/php/sdk/versions.yml +++ b/generators/php/sdk/versions.yml @@ -1,4 +1,14 @@ # yaml-language-server: $schema=../../../fern-versions-yml.schema.json +- version: 1.17.2 + changelogEntry: + - summary: | + Fix enum string escaping and PHP reserved keyword handling. + - Enum values containing quotes are now properly escaped to prevent syntax errors. + - Class names that conflict with PHP reserved keywords (e.g., "eval", "list") are automatically prefixed with the root namespace. + type: fix + createdAt: "2025-10-17" + irVersion: 59 + - version: 1.17.1 changelogEntry: - summary: | From 11b55929e406a670fb86b5b1f4a574b6627b95d9 Mon Sep 17 00:00:00 2001 From: Thomas Baker Date: Fri, 17 Oct 2025 14:17:07 -0400 Subject: [PATCH 3/8] Use trailing underscore for reserved keyword deconfliction Changed the reserved keyword handling to use a trailing underscore (e.g., Eval_) instead of namespace prefixing for class names. This is more idiomatic in PHP and follows similar conventions in other languages. Updated changelog to reflect the new approach. --- .../php/base/src/context/AbstractPhpGeneratorContext.ts | 4 ++-- .../src/context/DynamicSnippetsGeneratorContext.ts | 4 ++-- generators/php/sdk/versions.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/generators/php/base/src/context/AbstractPhpGeneratorContext.ts b/generators/php/base/src/context/AbstractPhpGeneratorContext.ts index 61b7f947c9f..8f29d6e6161 100644 --- a/generators/php/base/src/context/AbstractPhpGeneratorContext.ts +++ b/generators/php/base/src/context/AbstractPhpGeneratorContext.ts @@ -101,8 +101,8 @@ export abstract class AbstractPhpGeneratorContext< // Check if the class name is a reserved keyword (case-insensitive) if (PHP_RESERVED_KEYWORDS.has(className.toLowerCase())) { - // Prefix with the root namespace name to avoid collision - return `${this.rootNamespace}${className}`; + // Add trailing underscore to avoid collision + return `${className}_`; } return className; diff --git a/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts b/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts index 3a56ed88a92..3b82cf6d173 100644 --- a/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts +++ b/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts @@ -82,8 +82,8 @@ export class DynamicSnippetsGeneratorContext extends AbstractDynamicSnippetsGene // Check if the class name is a reserved keyword (case-insensitive) if (PHP_RESERVED_KEYWORDS.has(className.toLowerCase())) { - // Prefix with the root namespace name to avoid collision - return `${this.rootNamespace}${className}`; + // Add trailing underscore to avoid collision + return `${className}_`; } return className; diff --git a/generators/php/sdk/versions.yml b/generators/php/sdk/versions.yml index 37983f8e833..400162aa53a 100644 --- a/generators/php/sdk/versions.yml +++ b/generators/php/sdk/versions.yml @@ -4,7 +4,7 @@ - summary: | Fix enum string escaping and PHP reserved keyword handling. - Enum values containing quotes are now properly escaped to prevent syntax errors. - - Class names that conflict with PHP reserved keywords (e.g., "eval", "list") are automatically prefixed with the root namespace. + - Class names that conflict with PHP reserved keywords (e.g., "eval", "list") automatically receive a trailing underscore (e.g., "Eval_"). type: fix createdAt: "2025-10-17" irVersion: 59 From 63508b024c628ee84a5f66f27360089474a7de68 Mon Sep 17 00:00:00 2001 From: Thomas Baker Date: Fri, 17 Oct 2025 16:40:10 -0400 Subject: [PATCH 4/8] Extract PHP reserved keywords to shared constants Moved PHP_RESERVED_KEYWORDS from inline definitions to a shared constant in the codegen package to avoid duplication. This ensures the keyword list is maintained in a single location and can be imported by both the base and dynamic-snippets contexts. --- .../src/context/AbstractPhpGeneratorContext.ts | 17 +---------------- generators/php/codegen/src/constants.ts | 14 ++++++++++++++ generators/php/codegen/src/index.ts | 1 + .../context/DynamicSnippetsGeneratorContext.ts | 17 +---------------- 4 files changed, 17 insertions(+), 32 deletions(-) create mode 100644 generators/php/codegen/src/constants.ts diff --git a/generators/php/base/src/context/AbstractPhpGeneratorContext.ts b/generators/php/base/src/context/AbstractPhpGeneratorContext.ts index 8f29d6e6161..9e9767a755f 100644 --- a/generators/php/base/src/context/AbstractPhpGeneratorContext.ts +++ b/generators/php/base/src/context/AbstractPhpGeneratorContext.ts @@ -1,7 +1,7 @@ import { AbstractGeneratorContext, FernGeneratorExec, GeneratorNotificationService } from "@fern-api/base-generator"; import { assertNever } from "@fern-api/core-utils"; import { RelativeFilePath } from "@fern-api/fs-utils"; -import { BasePhpCustomConfigSchema, GLOBAL_NAMESPACE, php, SELF } from "@fern-api/php-codegen"; +import { BasePhpCustomConfigSchema, GLOBAL_NAMESPACE, php, PHP_RESERVED_KEYWORDS, SELF } from "@fern-api/php-codegen"; import { FernFilepath, IntermediateRepresentation, @@ -84,21 +84,6 @@ export abstract class AbstractPhpGeneratorContext< public getClassName(name: Name): string { const className = name.pascalCase.safeName; - // PHP reserved keywords (case-insensitive) that cannot be used as class names - // Source: https://www.php.net/manual/en/reserved.keywords.php - const PHP_RESERVED_KEYWORDS = new Set([ - "abstract", "and", "array", "as", "break", "callable", "case", "catch", - "class", "clone", "const", "continue", "declare", "default", "die", "do", - "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", - "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", - "finally", "fn", "for", "foreach", "function", "global", "goto", "if", - "implements", "include", "include_once", "instanceof", "insteadof", - "interface", "isset", "list", "match", "namespace", "new", "or", "print", - "private", "protected", "public", "readonly", "require", "require_once", - "return", "static", "switch", "throw", "trait", "try", "unset", "use", - "var", "while", "xor", "yield", "yield_from", "__halt_compiler" - ]); - // Check if the class name is a reserved keyword (case-insensitive) if (PHP_RESERVED_KEYWORDS.has(className.toLowerCase())) { // Add trailing underscore to avoid collision diff --git a/generators/php/codegen/src/constants.ts b/generators/php/codegen/src/constants.ts new file mode 100644 index 00000000000..3705952be75 --- /dev/null +++ b/generators/php/codegen/src/constants.ts @@ -0,0 +1,14 @@ +// PHP reserved keywords (case-insensitive) that cannot be used as class names +// Source: https://www.php.net/manual/en/reserved.keywords.php +export const PHP_RESERVED_KEYWORDS = new Set([ + "abstract", "and", "array", "as", "break", "callable", "case", "catch", + "class", "clone", "const", "continue", "declare", "default", "die", "do", + "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", + "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", + "finally", "fn", "for", "foreach", "function", "global", "goto", "if", + "implements", "include", "include_once", "instanceof", "insteadof", + "interface", "isset", "list", "match", "namespace", "new", "or", "print", + "private", "protected", "public", "readonly", "require", "require_once", + "return", "static", "switch", "throw", "trait", "try", "unset", "use", + "var", "while", "xor", "yield", "yield_from", "__halt_compiler" +]); diff --git a/generators/php/codegen/src/index.ts b/generators/php/codegen/src/index.ts index 26f7b1f393a..3293ddf54af 100644 --- a/generators/php/codegen/src/index.ts +++ b/generators/php/codegen/src/index.ts @@ -1,3 +1,4 @@ export { GLOBAL_NAMESPACE, SELF, STATIC } from "./ast/core/Constant"; export { BasePhpCustomConfigSchema } from "./custom-config/BasePhpCustomConfigSchema"; +export { PHP_RESERVED_KEYWORDS } from "./constants"; export * as php from "./php"; diff --git a/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts b/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts index 3b82cf6d173..a8fd3bbcf58 100644 --- a/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts +++ b/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts @@ -3,7 +3,7 @@ import { FernGeneratorExec } from "@fern-api/browser-compatible-base-generator"; import { FernIr } from "@fern-api/dynamic-ir-sdk"; -import { BasePhpCustomConfigSchema, php } from "@fern-api/php-codegen"; +import { BasePhpCustomConfigSchema, php, PHP_RESERVED_KEYWORDS } from "@fern-api/php-codegen"; import { camelCase, upperFirst } from "lodash-es"; import { DynamicTypeLiteralMapper } from "./DynamicTypeLiteralMapper"; @@ -65,21 +65,6 @@ export class DynamicSnippetsGeneratorContext extends AbstractDynamicSnippetsGene public getClassName(name: FernIr.Name): string { const className = name.pascalCase.safeName; - // PHP reserved keywords (case-insensitive) that cannot be used as class names - // Source: https://www.php.net/manual/en/reserved.keywords.php - const PHP_RESERVED_KEYWORDS = new Set([ - "abstract", "and", "array", "as", "break", "callable", "case", "catch", - "class", "clone", "const", "continue", "declare", "default", "die", "do", - "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", - "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", - "finally", "fn", "for", "foreach", "function", "global", "goto", "if", - "implements", "include", "include_once", "instanceof", "insteadof", - "interface", "isset", "list", "match", "namespace", "new", "or", "print", - "private", "protected", "public", "readonly", "require", "require_once", - "return", "static", "switch", "throw", "trait", "try", "unset", "use", - "var", "while", "xor", "yield", "yield_from", "__halt_compiler" - ]); - // Check if the class name is a reserved keyword (case-insensitive) if (PHP_RESERVED_KEYWORDS.has(className.toLowerCase())) { // Add trailing underscore to avoid collision From af36afa0f01e661a2f435323afaa1c44de5a42c2 Mon Sep 17 00:00:00 2001 From: Thomas Baker Date: Fri, 17 Oct 2025 16:43:10 -0400 Subject: [PATCH 5/8] Refactor getClassName to use shared utility function Extracted the class name sanitization logic from both context implementations into a shared getSafeClassName() utility function in the codegen package. This eliminates code duplication and provides a single, reusable implementation. --- .../src/context/AbstractPhpGeneratorContext.ts | 12 ++---------- generators/php/codegen/src/index.ts | 1 + generators/php/codegen/src/utils.ts | 15 +++++++++++++++ .../context/DynamicSnippetsGeneratorContext.ts | 12 ++---------- 4 files changed, 20 insertions(+), 20 deletions(-) create mode 100644 generators/php/codegen/src/utils.ts diff --git a/generators/php/base/src/context/AbstractPhpGeneratorContext.ts b/generators/php/base/src/context/AbstractPhpGeneratorContext.ts index 9e9767a755f..4b5c68ea2e0 100644 --- a/generators/php/base/src/context/AbstractPhpGeneratorContext.ts +++ b/generators/php/base/src/context/AbstractPhpGeneratorContext.ts @@ -1,7 +1,7 @@ import { AbstractGeneratorContext, FernGeneratorExec, GeneratorNotificationService } from "@fern-api/base-generator"; import { assertNever } from "@fern-api/core-utils"; import { RelativeFilePath } from "@fern-api/fs-utils"; -import { BasePhpCustomConfigSchema, GLOBAL_NAMESPACE, php, PHP_RESERVED_KEYWORDS, SELF } from "@fern-api/php-codegen"; +import { BasePhpCustomConfigSchema, getSafeClassName, GLOBAL_NAMESPACE, php, SELF } from "@fern-api/php-codegen"; import { FernFilepath, IntermediateRepresentation, @@ -82,15 +82,7 @@ export abstract class AbstractPhpGeneratorContext< } public getClassName(name: Name): string { - const className = name.pascalCase.safeName; - - // Check if the class name is a reserved keyword (case-insensitive) - if (PHP_RESERVED_KEYWORDS.has(className.toLowerCase())) { - // Add trailing underscore to avoid collision - return `${className}_`; - } - - return className; + return getSafeClassName(name.pascalCase.safeName); } public getGlobalNamespace(): string { diff --git a/generators/php/codegen/src/index.ts b/generators/php/codegen/src/index.ts index 3293ddf54af..a79f755f8bc 100644 --- a/generators/php/codegen/src/index.ts +++ b/generators/php/codegen/src/index.ts @@ -1,4 +1,5 @@ export { GLOBAL_NAMESPACE, SELF, STATIC } from "./ast/core/Constant"; export { BasePhpCustomConfigSchema } from "./custom-config/BasePhpCustomConfigSchema"; export { PHP_RESERVED_KEYWORDS } from "./constants"; +export { getSafeClassName } from "./utils"; export * as php from "./php"; diff --git a/generators/php/codegen/src/utils.ts b/generators/php/codegen/src/utils.ts new file mode 100644 index 00000000000..9167b3fa84f --- /dev/null +++ b/generators/php/codegen/src/utils.ts @@ -0,0 +1,15 @@ +import { PHP_RESERVED_KEYWORDS } from "./constants"; + +/** + * Returns a safe class name, adding a trailing underscore if the name + * conflicts with a PHP reserved keyword. + */ +export function getSafeClassName(className: string): string { + // Check if the class name is a reserved keyword (case-insensitive) + if (PHP_RESERVED_KEYWORDS.has(className.toLowerCase())) { + // Add trailing underscore to avoid collision + return `${className}_`; + } + + return className; +} diff --git a/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts b/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts index a8fd3bbcf58..927daac1b11 100644 --- a/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts +++ b/generators/php/dynamic-snippets/src/context/DynamicSnippetsGeneratorContext.ts @@ -3,7 +3,7 @@ import { FernGeneratorExec } from "@fern-api/browser-compatible-base-generator"; import { FernIr } from "@fern-api/dynamic-ir-sdk"; -import { BasePhpCustomConfigSchema, php, PHP_RESERVED_KEYWORDS } from "@fern-api/php-codegen"; +import { BasePhpCustomConfigSchema, getSafeClassName, php } from "@fern-api/php-codegen"; import { camelCase, upperFirst } from "lodash-es"; import { DynamicTypeLiteralMapper } from "./DynamicTypeLiteralMapper"; @@ -63,15 +63,7 @@ export class DynamicSnippetsGeneratorContext extends AbstractDynamicSnippetsGene } public getClassName(name: FernIr.Name): string { - const className = name.pascalCase.safeName; - - // Check if the class name is a reserved keyword (case-insensitive) - if (PHP_RESERVED_KEYWORDS.has(className.toLowerCase())) { - // Add trailing underscore to avoid collision - return `${className}_`; - } - - return className; + return getSafeClassName(name.pascalCase.safeName); } public getRootClientClassName(): string { From e7a1aad74fe98fdaa9c5922bc515856e4b4b135d Mon Sep 17 00:00:00 2001 From: Thomas Baker Date: Fri, 17 Oct 2025 16:44:21 -0400 Subject: [PATCH 6/8] Run pnpm format:fix --- generators/php/codegen/src/constants.ts | 81 ++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/generators/php/codegen/src/constants.ts b/generators/php/codegen/src/constants.ts index 3705952be75..7c161970027 100644 --- a/generators/php/codegen/src/constants.ts +++ b/generators/php/codegen/src/constants.ts @@ -1,14 +1,75 @@ // PHP reserved keywords (case-insensitive) that cannot be used as class names // Source: https://www.php.net/manual/en/reserved.keywords.php export const PHP_RESERVED_KEYWORDS = new Set([ - "abstract", "and", "array", "as", "break", "callable", "case", "catch", - "class", "clone", "const", "continue", "declare", "default", "die", "do", - "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", - "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", - "finally", "fn", "for", "foreach", "function", "global", "goto", "if", - "implements", "include", "include_once", "instanceof", "insteadof", - "interface", "isset", "list", "match", "namespace", "new", "or", "print", - "private", "protected", "public", "readonly", "require", "require_once", - "return", "static", "switch", "throw", "trait", "try", "unset", "use", - "var", "while", "xor", "yield", "yield_from", "__halt_compiler" + "abstract", + "and", + "array", + "as", + "break", + "callable", + "case", + "catch", + "class", + "clone", + "const", + "continue", + "declare", + "default", + "die", + "do", + "echo", + "else", + "elseif", + "empty", + "enddeclare", + "endfor", + "endforeach", + "endif", + "endswitch", + "endwhile", + "eval", + "exit", + "extends", + "final", + "finally", + "fn", + "for", + "foreach", + "function", + "global", + "goto", + "if", + "implements", + "include", + "include_once", + "instanceof", + "insteadof", + "interface", + "isset", + "list", + "match", + "namespace", + "new", + "or", + "print", + "private", + "protected", + "public", + "readonly", + "require", + "require_once", + "return", + "static", + "switch", + "throw", + "trait", + "try", + "unset", + "use", + "var", + "while", + "xor", + "yield", + "yield_from", + "__halt_compiler" ]); From 0808d3c59af00222195f5bf04d623a4573cfdb08 Mon Sep 17 00:00:00 2001 From: Thomas Baker Date: Fri, 17 Oct 2025 16:45:56 -0400 Subject: [PATCH 7/8] check fix --- .../php/base/src/context/AbstractPhpGeneratorContext.ts | 2 +- generators/php/codegen/src/index.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/generators/php/base/src/context/AbstractPhpGeneratorContext.ts b/generators/php/base/src/context/AbstractPhpGeneratorContext.ts index 4b5c68ea2e0..250ca767c19 100644 --- a/generators/php/base/src/context/AbstractPhpGeneratorContext.ts +++ b/generators/php/base/src/context/AbstractPhpGeneratorContext.ts @@ -1,7 +1,7 @@ import { AbstractGeneratorContext, FernGeneratorExec, GeneratorNotificationService } from "@fern-api/base-generator"; import { assertNever } from "@fern-api/core-utils"; import { RelativeFilePath } from "@fern-api/fs-utils"; -import { BasePhpCustomConfigSchema, getSafeClassName, GLOBAL_NAMESPACE, php, SELF } from "@fern-api/php-codegen"; +import { BasePhpCustomConfigSchema, GLOBAL_NAMESPACE, getSafeClassName, php, SELF } from "@fern-api/php-codegen"; import { FernFilepath, IntermediateRepresentation, diff --git a/generators/php/codegen/src/index.ts b/generators/php/codegen/src/index.ts index a79f755f8bc..090253a24f6 100644 --- a/generators/php/codegen/src/index.ts +++ b/generators/php/codegen/src/index.ts @@ -1,5 +1,5 @@ export { GLOBAL_NAMESPACE, SELF, STATIC } from "./ast/core/Constant"; -export { BasePhpCustomConfigSchema } from "./custom-config/BasePhpCustomConfigSchema"; export { PHP_RESERVED_KEYWORDS } from "./constants"; -export { getSafeClassName } from "./utils"; +export { BasePhpCustomConfigSchema } from "./custom-config/BasePhpCustomConfigSchema"; export * as php from "./php"; +export { getSafeClassName } from "./utils"; From 5a61819ce493f11dc24262fcba0177a3021b8579 Mon Sep 17 00:00:00 2001 From: Thomas Baker Date: Fri, 17 Oct 2025 16:46:38 -0400 Subject: [PATCH 8/8] include co authored by --- .claude/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.claude/settings.json b/.claude/settings.json index 43955c7e104..a1a19b11870 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -58,6 +58,6 @@ "NODE_ENV": "development", "PNPM_VERSION": "9.4.0" }, - "includeCoAuthoredBy": false, + "includeCoAuthoredBy": true, "model": "claude-sonnet-4-20250514" }