@voxgig/sdkgen 4.2.8 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/helpers/naming.d.ts +2 -1
  3. package/dist/helpers/naming.js +50 -12
  4. package/dist/helpers/naming.js.map +1 -1
  5. package/dist/sdkgen.d.ts +2 -2
  6. package/dist/sdkgen.js +4 -3
  7. package/dist/sdkgen.js.map +1 -1
  8. package/dist/tsconfig.tsbuildinfo +1 -1
  9. package/package.json +1 -1
  10. package/project/.sdk/src/cmp/zig/Config_zig.ts +1 -1
  11. package/project/.sdk/tm/c/tests/primary_corpus_test.c +565 -0
  12. package/project/.sdk/tm/c/utility/prepare_method.c +3 -1
  13. package/project/.sdk/tm/c/utility/transform_request.c +4 -3
  14. package/project/.sdk/tm/clojure/src/sdk/core.clj +55 -5
  15. package/project/.sdk/tm/clojure/test/sdk/test/primary.clj +171 -1
  16. package/project/.sdk/tm/clojure/test/sdk/test/struct_corpus.clj +13 -2
  17. package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +2 -0
  18. package/project/.sdk/tm/csharp/test/CustomUtilityTest.cs +104 -0
  19. package/project/.sdk/tm/csharp/utility/MakeOptions.cs +82 -2
  20. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +50 -2
  21. package/project/.sdk/tm/elixir/test/primary_utility_test.exs +18 -200
  22. package/project/.sdk/tm/elixir/test/support/struct_corpus.ex +413 -2
  23. package/project/.sdk/tm/go/test/custom_utility_test.go +103 -0
  24. package/project/.sdk/tm/go/test/feature_corpus_test.go +550 -0
  25. package/project/.sdk/tm/go/utility/make_options.go +7 -1
  26. package/project/.sdk/tm/go/utility/register.go +194 -0
  27. package/project/.sdk/tm/java/test/CustomUtilityTest.java +55 -0
  28. package/project/.sdk/tm/java/test/FeatureCorpusTest.java +463 -0
  29. package/project/.sdk/tm/java/utility/MakeOptions.java +11 -2
  30. package/project/.sdk/tm/java/utility/Register.java +91 -0
  31. package/project/.sdk/tm/js/test/feature/Corpus.test.js +285 -0
  32. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +56 -2
  33. package/project/.sdk/tm/lua/utility/make_options.lua +22 -2
  34. package/project/.sdk/tm/ocaml/Makefile +15 -4
  35. package/project/.sdk/tm/ocaml/sdk_runtime.ml +8 -1
  36. package/project/.sdk/tm/ocaml/test/corpus_runner.ml +185 -0
  37. package/project/.sdk/tm/ocaml/test/primary_utility_test.ml +238 -0
  38. package/project/.sdk/tm/ocaml/test/struct_corpus.ml +5 -160
  39. package/project/.sdk/tm/perl/t/feature_corpus.t +345 -0
  40. package/project/.sdk/tm/perl/utility/make_options.pm +33 -1
  41. package/project/.sdk/tm/php/core/Context.php +3 -0
  42. package/project/.sdk/tm/php/core/Control.php +13 -0
  43. package/project/.sdk/tm/php/core/Error.php +12 -0
  44. package/project/.sdk/tm/php/test/FeatureCorpusTest.php +376 -0
  45. package/project/.sdk/tm/php/utility/MakeOptions.php +30 -1
  46. package/project/.sdk/tm/py/pkg/utility/make_options.py +42 -1
  47. package/project/.sdk/tm/py/test/test_feature_corpus.py +309 -0
  48. package/project/.sdk/tm/rb/test/feature_corpus_test.rb +281 -0
  49. package/project/.sdk/tm/rb/utility/make_options.rb +32 -1
  50. package/project/.sdk/tm/scala/Makefile +1 -0
  51. package/project/.sdk/tm/scala/sdktest/PrimaryCorpus.scala +294 -0
  52. package/project/.sdk/tm/scala/sdktest/StructCorpus.scala +0 -0
  53. package/project/.sdk/tm/scala/utility/Make.scala +49 -2
  54. package/project/.sdk/tm/scala/utility/Prepare.scala +3 -1
  55. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +21 -3
  56. package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +13 -2
  57. package/project/.sdk/tm/ts/test/feature/Corpus.test.ts +287 -0
  58. package/project/.sdk/tm/zig/core/utility.zig +8 -1
  59. package/project/.sdk/tm/zig/test/primary_utility_test.zig +445 -0
  60. package/project/.sdk/tm/zig/test/struct_runner.zig +238 -0
  61. package/project/sdkgen-package.json +1 -1
  62. package/src/helpers/naming.ts +54 -12
  63. package/src/sdkgen.ts +2 -1
@@ -2,6 +2,7 @@
2
2
  // against subject functions, mirroring the TS/Go runner pattern.
3
3
 
4
4
  const std = @import("std");
5
+ const regex = @import("../utility/voxgigstruct/regex.zig");
5
6
  const voxgig_struct = @import("voxgig-struct");
6
7
 
7
8
  const Allocator = std.mem.Allocator;
@@ -20,6 +21,22 @@ pub const Subject = *const fn (StdJsonValue) StdJsonValue;
20
21
  // Subject that takes an allocator and our JsonValue type.
21
22
  pub const AllocSubject = *const fn (Allocator, JsonValue) JsonValue;
22
23
 
24
+ /// A subject that receives the whole corpus ENTRY and returns std.json.
25
+ ///
26
+ /// `published` is an out-parameter for the context the subject built. std.json
27
+ /// maps cannot be mutated in place safely from here — a put may reallocate the
28
+ /// backing store and the caller would never see it — so a section that needs a
29
+ /// `match: ctx.*` assertion hands its ctx back through this instead.
30
+ pub const EntrySubject = *const fn (
31
+ Allocator,
32
+ StdJsonValue,
33
+ *?StdJsonValue,
34
+ /// The SDK's own error message. Zig errors carry no payload, so
35
+ /// @errorName gives the tag ("Sdk") and never the text the corpus matches
36
+ /// on. A subject that fails writes ctx.pending_err's message here.
37
+ *?[]const u8,
38
+ ) anyerror!StdJsonValue;
39
+
23
40
  pub const Spec = struct {
24
41
  data: StdJsonValue,
25
42
 
@@ -35,6 +52,8 @@ pub const RunPack = struct {
35
52
  spec: Spec,
36
53
  allocator: Allocator,
37
54
  file_data: []const u8,
55
+ /// Cases actually executed, so a suite can assert it ran something.
56
+ ran: usize = 0,
38
57
  parsed: std.json.Parsed(StdJsonValue),
39
58
 
40
59
  /// Run all entries in testspec.set against the subject function (no alloc, std types).
@@ -125,6 +144,101 @@ pub const RunPack = struct {
125
144
  }
126
145
  }
127
146
 
147
+ /// Drive a section whose entries carry ctx/args/match/err.
148
+ ///
149
+ /// The subject receives the whole ENTRY, not the resolved args, because an
150
+ /// args-style section has to publish the context it builds back onto the
151
+ /// entry — a `match: ctx.*` assertion reads it from there.
152
+ pub fn runsetEntry(self: *RunPack, testspec: StdJsonValue, subject: EntrySubject) !void {
153
+ const set_val = switch (testspec) {
154
+ .object => |obj| obj.get("set") orelse return,
155
+ else => return,
156
+ };
157
+ if (set_val != .array) return;
158
+
159
+ var failures: usize = 0;
160
+
161
+ for (set_val.array.items, 0..) |entry_val, entry_idx| {
162
+ if (entry_val != .object) continue;
163
+ const entry = entry_val.object;
164
+
165
+ var arena = std.heap.ArenaAllocator.init(self.allocator);
166
+ defer arena.deinit();
167
+ const alloc = arena.allocator();
168
+
169
+ const err_field = entry.get("err");
170
+
171
+ self.ran += 1;
172
+ var published: ?StdJsonValue = null;
173
+ var errmsg: ?[]const u8 = null;
174
+
175
+ const res = subject(alloc, entry_val, &published, &errmsg) catch |e| {
176
+ // An expected error: match its text, then any `match` block.
177
+ if (err_field) |ef| {
178
+ const msg = errmsg orelse @errorName(e);
179
+ if (ef == .bool and ef.bool) continue;
180
+ if (matchval(alloc, ef, StdJsonValue{ .string = msg })) continue;
181
+ std.debug.print("\n ERROR MATCH [entry {d}]: [{s}] <=> [{s}]\n", .{
182
+ entry_idx, fmtJson(ef), msg,
183
+ });
184
+ }
185
+ failures += 1;
186
+ continue;
187
+ };
188
+
189
+ if (err_field != null) {
190
+ std.debug.print("\n expected an error [entry {d}]\n", .{entry_idx});
191
+ failures += 1;
192
+ continue;
193
+ }
194
+
195
+ var matched = false;
196
+
197
+ if (entry.get("match")) |m| {
198
+ var subj = std.json.ObjectMap.init(alloc);
199
+ subj.put("out", res) catch {};
200
+ if (entry.get("in")) |v| subj.put("in", v) catch {};
201
+ if (published) |p| {
202
+ subj.put("ctx", p) catch {};
203
+ } else if (entry.get("ctx")) |v| {
204
+ subj.put("ctx", v) catch {};
205
+ }
206
+ const subjval = StdJsonValue{ .object = subj };
207
+
208
+ var path = std.ArrayList([]const u8).init(alloc);
209
+ doMatch(alloc, m, subjval, &path) catch {
210
+ std.debug.print(" [entry {d}]\n", .{entry_idx});
211
+ failures += 1;
212
+ continue;
213
+ };
214
+ matched = true;
215
+ }
216
+
217
+ const raw_out = entry.get("out");
218
+
219
+ if (raw_out) |o| {
220
+ if (jsonEqual(o, res)) continue;
221
+ if (o == .string and std.mem.eql(u8, o.string, NULLMARK) and res == .null) continue;
222
+ std.debug.print("\n FAIL [entry {d}]: expected {s} got {s}\n", .{
223
+ entry_idx, fmtJson(o), fmtJson(res),
224
+ });
225
+ failures += 1;
226
+ } else if (!matched) {
227
+ // NO `out` MEANS EXPECT NULL, not "assert nothing". The
228
+ // reference sets a missing out to the null marker before
229
+ // running, so an entry like {"ctx": {"opname": "bad"}} asserts
230
+ // that the utility yields nothing.
231
+ if (res == .null) continue;
232
+ std.debug.print("\n FAIL [entry {d}]: expected null got {s}\n", .{
233
+ entry_idx, fmtJson(res),
234
+ });
235
+ failures += 1;
236
+ }
237
+ }
238
+
239
+ if (0 < failures) return error.SectionFailed;
240
+ }
241
+
128
242
  pub fn deinit(self: *RunPack) void {
129
243
  self.parsed.deinit();
130
244
  self.allocator.free(self.file_data);
@@ -136,6 +250,29 @@ pub const Flags = struct {
136
250
  undef_as_null: bool = true,
137
251
  };
138
252
 
253
+ /// Load test.json and return a named top-level spec section.
254
+ ///
255
+ /// makeRunner is this with "struct" baked in. The primary-utility suite needs
256
+ /// "primary" from the same file, and duplicating the load would give the two
257
+ /// suites separate copies of a corpus that is meant to be shared.
258
+ pub fn makeRunnerFor(allocator: Allocator, section: []const u8) !RunPack {
259
+ const data = try std.fs.cwd().readFileAlloc(allocator, TEST_JSON_FILE, 10 * 1024 * 1024);
260
+ const parsed = try std.json.parseFromSlice(StdJsonValue, allocator, data, .{});
261
+ const root = parsed.value;
262
+
263
+ const spec_val = switch (root) {
264
+ .object => |obj| obj.get(section) orelse return error.NoSectionInTestJson,
265
+ else => return error.TestJsonNotObject,
266
+ };
267
+
268
+ return RunPack{
269
+ .spec = Spec{ .data = spec_val },
270
+ .allocator = allocator,
271
+ .file_data = data,
272
+ .parsed = parsed,
273
+ };
274
+ }
275
+
139
276
  /// Load test.json and return the "struct" spec.
140
277
  pub fn makeRunner(allocator: Allocator) !RunPack {
141
278
  const path = TEST_JSON_FILE;
@@ -156,6 +293,107 @@ pub fn makeRunner(allocator: Allocator) !RunPack {
156
293
  };
157
294
  }
158
295
 
296
+ // ---- Corpus matching: matchval / doMatch ----
297
+ //
298
+ // The primary corpus asserts with `match` as often as with `out`, and its
299
+ // error expectations are regexes. runsetAlloc resolved only `in`, had no
300
+ // match support and silently skipped any entry carrying `err` — so it could
301
+ // drive the struct corpus but not this one. Semantics are the reference's:
302
+ // exact equality first, then __UNDEF__/__EXISTS__ markers, then a /regex/, and
303
+ // finally a case-insensitive substring.
304
+
305
+ fn stringifyAlloc(alloc: Allocator, v: StdJsonValue) []const u8 {
306
+ var buf = std.ArrayList(u8).init(alloc);
307
+ if (v == .string) return v.string;
308
+ std.json.stringify(v, .{}, buf.writer()) catch return "";
309
+ return buf.items;
310
+ }
311
+
312
+ pub fn matchval(alloc: Allocator, check: StdJsonValue, base: StdJsonValue) bool {
313
+ if (jsonEqual(check, base)) return true;
314
+
315
+ if (check == .string) {
316
+ const c = check.string;
317
+ if (std.mem.eql(u8, c, UNDEFMARK)) return base == .null;
318
+ if (std.mem.eql(u8, c, EXISTSMARK)) return base != .null;
319
+
320
+ const basestr = stringifyAlloc(alloc, base);
321
+
322
+ // A /pattern/ is a regex over the stringified base.
323
+ if (2 <= c.len and c[0] == '/' and c[c.len - 1] == '/') {
324
+ const pat = c[1 .. c.len - 1];
325
+ var re = regex.compile(alloc, pat) orelse return false;
326
+ defer re.deinit();
327
+ return re.isMatch(basestr);
328
+ }
329
+
330
+ // Otherwise a case-insensitive substring, as the reference does.
331
+ const lc_base = std.ascii.allocLowerString(alloc, basestr) catch return false;
332
+ const lc_check = std.ascii.allocLowerString(alloc, c) catch return false;
333
+ return std.mem.indexOf(u8, lc_base, lc_check) != null;
334
+ }
335
+
336
+ return false;
337
+ }
338
+
339
+ fn getPath(base: StdJsonValue, path: []const []const u8) StdJsonValue {
340
+ var cur = base;
341
+ for (path) |seg| {
342
+ switch (cur) {
343
+ .object => |o| cur = o.get(seg) orelse return StdJsonValue{ .null = {} },
344
+ .array => |a| {
345
+ const idx = std.fmt.parseInt(usize, seg, 10) catch return StdJsonValue{ .null = {} };
346
+ if (idx >= a.items.len) return StdJsonValue{ .null = {} };
347
+ cur = a.items[idx];
348
+ },
349
+ else => return StdJsonValue{ .null = {} },
350
+ }
351
+ }
352
+ return cur;
353
+ }
354
+
355
+ /// Walk `check`; every LEAF must matchval against the same path in `base`.
356
+ pub fn doMatch(
357
+ alloc: Allocator,
358
+ check: StdJsonValue,
359
+ base: StdJsonValue,
360
+ path: *std.ArrayList([]const u8),
361
+ ) !void {
362
+ switch (check) {
363
+ .object => |o| {
364
+ var it = o.iterator();
365
+ while (it.next()) |kv| {
366
+ try path.append(kv.key_ptr.*);
367
+ try doMatch(alloc, kv.value_ptr.*, base, path);
368
+ _ = path.pop();
369
+ }
370
+ },
371
+ .array => |a| {
372
+ for (a.items, 0..) |item, i| {
373
+ const seg = try std.fmt.allocPrint(alloc, "{d}", .{i});
374
+ try path.append(seg);
375
+ try doMatch(alloc, item, base, path);
376
+ _ = path.pop();
377
+ }
378
+ },
379
+ else => {
380
+ const baseval = getPath(base, path.items);
381
+ if (!matchval(alloc, check, baseval)) {
382
+ std.debug.print("\n MATCH: {s}: [{s}] <=> [{s}]\n", .{
383
+ joinPath(alloc, path.items),
384
+ fmtJson(check),
385
+ fmtJson(baseval),
386
+ });
387
+ return error.MatchMismatch;
388
+ }
389
+ },
390
+ }
391
+ }
392
+
393
+ fn joinPath(alloc: Allocator, parts: []const []const u8) []const u8 {
394
+ return std.mem.join(alloc, ".", parts) catch "?";
395
+ }
396
+
159
397
  // ---- Result comparison (operates on std.json.Value) ----
160
398
 
161
399
  fn checkResult(expected: StdJsonValue, result: StdJsonValue) !void {
@@ -3,7 +3,7 @@
3
3
  "package": 1
4
4
  },
5
5
  "name": "@voxgig/sdkgen",
6
- "version": "4.2.8",
6
+ "version": "4.4.0",
7
7
  "provides": {
8
8
  "target": [
9
9
  "c",
@@ -149,9 +149,9 @@ const RB_SDK_CONSTANTS = new Set<string>([
149
149
  'StructRunner', 'StructTestClient', 'StructUtilityTest', 'VoxgigStruct',
150
150
  'STRUCT_TEST_JSON_FILE',
151
151
  // the generated/templated test classes
152
- 'ExistsTest', 'FeatureTest', 'NetsimTest', 'PipelineTest',
153
- 'PrimaryUtilityTest', 'ReadmeExamplesTest', 'TestHookFeature',
154
- 'TestInitFeature',
152
+ 'ExistsTest', 'FeatureCorpusTest', 'FeatureTest', 'NetsimTest',
153
+ 'PipelineTest', 'PrimaryUtilityTest', 'ReadmeExamplesTest',
154
+ 'TestHookFeature', 'TestInitFeature',
155
155
  ])
156
156
 
157
157
 
@@ -304,18 +304,59 @@ function isPhpReservedType(Name: string): boolean {
304
304
  }
305
305
 
306
306
 
307
- // A declarable PHP class name for a generated type: unchanged, unless PHP
308
- // reserves the word, in which case `Type` is appended (`Namespace` ->
309
- // `NamespaceType`). Mirrors rbSafeTypeName and swiftSafeTypeName deliberately
310
- // same suffix, same "only rename on an actual collision" rule, so every SDK
311
- // that does not collide is byte-identical to before.
307
+ // CLASSES THE GENERATED PHP SDK ITSELF DECLARES the second half of "already
308
+ // taken", exactly as RB_SDK_CONSTANTS is for ruby. `PHP_RESERVED_TYPES` covers
309
+ // what the LANGUAGE owns; this covers what OUR OWN scaffolding claims, which a
310
+ // keyword list can never catch.
311
+ //
312
+ // The generated PHP SDK uses NO NAMESPACES, and composer classmaps both the
313
+ // runtime (`types/`) and the tests (`autoload-dev`: `test/`). An entity named
314
+ // `feature_test` emits `class FeatureTest` in `<Sdk>Types.php` while
315
+ // `tm/php/test/FeatureTest.php` declares one too: composer maps one name to
316
+ // two files, and loading both fatals on redeclaration. Ruby's equivalent only
317
+ // warns; PHP does not.
318
+ //
319
+ // Only UNPREFIXED, UNNAMESPACED declarations are listed. `ProjectNameUtility`
320
+ // substitutes to `<Sdk>Utility`, which no bare entity type can equal, and
321
+ // `utility/struct/Struct.php` and `test/StructRunner.php` declare inside a
322
+ // namespace — neither is reachable from the global name an entity type takes.
323
+ //
324
+ // `php-sdk-classes.test.ts` re-derives this from the templates AND the
325
+ // components and fails on drift, the same discipline as the rb and swift
326
+ // guards, and for the same reason: a hand-collected list rots.
327
+ //
328
+ // Folded, and matched folded: PHP class names are case-insensitive, so
329
+ // `FeatureTest` and `featuretest` are one identifier.
330
+ const PHP_SDK_CLASSES = new Set<string>([
331
+ // the generated/templated test classes
332
+ 'existstest', 'featurecorpustest', 'featuretest', 'netsimtest',
333
+ 'pipelinetest', 'primaryutilitytest', 'readmeexamplestest',
334
+ 'structutilitytest',
335
+ // helper classes those suites declare beside them
336
+ 'ftclient', 'ftclock', 'ftctrl', 'ftentity', 'ftharness', 'ftrecorder',
337
+ 'plclient', 'plentity', 'plentityitem',
338
+ ])
339
+
340
+
341
+ // Does `Name` collide with a class the generated PHP SDK already declares?
342
+ function isPhpSdkClass(Name: string): boolean {
343
+ return PHP_SDK_CLASSES.has(String(Name).toLowerCase())
344
+ }
345
+
346
+
347
+ // A declarable PHP class name for a generated type: unchanged, unless the name
348
+ // is ALREADY TAKEN — by PHP itself, or by the SDK's own scaffolding — in which
349
+ // case `Type` is appended (`Namespace` -> `NamespaceType`). Mirrors
350
+ // rbSafeTypeName and swiftSafeTypeName deliberately — same suffix, same "only
351
+ // rename on an actual collision" rule, so every SDK that does not collide is
352
+ // byte-identical to before.
312
353
  //
313
354
  // Applied ONLY to the bare entity data class. Per-op type names already carry
314
- // their own suffix (`NamespaceLoadData`, `NamespaceCreateData`), which no
315
- // reserved word matches, and the entity ACCESSOR is a method rather than a
316
- // class — PHP resolves those separately — so the public surface is unchanged.
355
+ // their own suffix (`NamespaceLoadData`, `NamespaceCreateData`), which neither
356
+ // set matches, and the entity ACCESSOR is a method rather than a class — PHP
357
+ // resolves those separately — so the public surface is unchanged.
317
358
  function phpSafeTypeName(Name: string): string {
318
- return isPhpReservedType(Name) ? Name + 'Type' : Name
359
+ return isPhpReservedType(Name) || isPhpSdkClass(Name) ? Name + 'Type' : Name
319
360
  }
320
361
 
321
362
 
@@ -496,6 +537,7 @@ export {
496
537
  isSwiftSdkType,
497
538
  swiftSafeTypeName,
498
539
  isPhpReservedType,
540
+ isPhpSdkClass,
499
541
  phpSafeTypeName,
500
542
  isTsReservedType,
501
543
  tsSafeTypeName,
package/src/sdkgen.ts CHANGED
@@ -59,7 +59,7 @@ import { collectDeps } from './helpers/collectDeps'
59
59
  import type { DepEntry } from './helpers/collectDeps'
60
60
  import { canonToType, canonToDtype, canonKey, canonScalarKey } from './helpers/canonType'
61
61
  import { OP_SUFFIX, opTypeName, opParams, ownPoint, opActions, entityActions, entityPath, opRequestShape, entityIdField, entityDataIdField, entityOps, entityPrimaryOp, pickExampleEntity, entityClassName, entityTypeCollisions, warnEntityTypeCollisions, deriveEntityNames, entityCollection } from './helpers/opShape'
62
- import { isReservedName, safeVarName, exampleVarName, phpEntityAccessor, entityCacheField, isRbCoreConstant, isRbSdkConstant, rbSafeTypeName, isSwiftSdkType, swiftSafeTypeName, isPhpReservedType, phpSafeTypeName, isTsReservedType, tsSafeTypeName, jsProp, jsOptProp, jsKey } from './helpers/naming'
62
+ import { isReservedName, safeVarName, exampleVarName, phpEntityAccessor, entityCacheField, isRbCoreConstant, isRbSdkConstant, rbSafeTypeName, isSwiftSdkType, swiftSafeTypeName, isPhpReservedType, isPhpSdkClass, phpSafeTypeName, isTsReservedType, tsSafeTypeName, jsProp, jsOptProp, jsKey } from './helpers/naming'
63
63
  import { serverVariables, hasServerVariables } from './helpers/serverVars'
64
64
  import { primaryOpCall, idLiteral, matchArg, dataArg, litFor } from './helpers/opExample'
65
65
  import type { ExampleLang } from './helpers/opExample'
@@ -1126,6 +1126,7 @@ export {
1126
1126
  isSwiftSdkType,
1127
1127
  swiftSafeTypeName,
1128
1128
  isPhpReservedType,
1129
+ isPhpSdkClass,
1129
1130
  phpSafeTypeName,
1130
1131
  isTsReservedType,
1131
1132
  tsSafeTypeName,