typia 13.1.19 → 13.2.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 (169) hide show
  1. package/lib/executable/FileSystemIdentity.d.ts +23 -0
  2. package/lib/executable/FileSystemIdentity.js +30 -0
  3. package/lib/executable/FileSystemIdentity.js.map +1 -1
  4. package/lib/executable/FileSystemIdentity.mjs +4 -0
  5. package/lib/executable/FileSystemIdentity.mjs.map +1 -1
  6. package/lib/executable/TypiaGenerateWizard.js +15 -9
  7. package/lib/executable/TypiaGenerateWizard.js.map +1 -1
  8. package/lib/executable/TypiaGenerateWizard.mjs +11 -7
  9. package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
  10. package/lib/internal/_ProtobufReader.d.ts +18 -3
  11. package/lib/internal/_ProtobufReader.js +39 -11
  12. package/lib/internal/_ProtobufReader.js.map +1 -1
  13. package/lib/internal/_ProtobufReader.mjs +37 -10
  14. package/lib/internal/_ProtobufReader.mjs.map +1 -1
  15. package/lib/internal/_jsonStringifyArray.d.ts +1 -0
  16. package/lib/internal/_jsonStringifyArray.js +48 -0
  17. package/lib/internal/_jsonStringifyArray.js.map +1 -0
  18. package/lib/internal/_jsonStringifyArray.mjs +40 -0
  19. package/lib/internal/_jsonStringifyArray.mjs.map +1 -0
  20. package/lib/internal/_jsonStringifyElement.d.ts +1 -0
  21. package/lib/internal/_jsonStringifyElement.js +23 -0
  22. package/lib/internal/_jsonStringifyElement.js.map +1 -0
  23. package/lib/internal/_jsonStringifyElement.mjs +23 -0
  24. package/lib/internal/_jsonStringifyElement.mjs.map +1 -0
  25. package/lib/internal/_jsonStringifyProperty.d.ts +1 -0
  26. package/lib/internal/_jsonStringifyProperty.js +31 -0
  27. package/lib/internal/_jsonStringifyProperty.js.map +1 -0
  28. package/lib/internal/_jsonStringifyProperty.mjs +31 -0
  29. package/lib/internal/_jsonStringifyProperty.mjs.map +1 -0
  30. package/lib/internal/_llmApplicationFinalize.js +1 -1
  31. package/lib/internal/_llmApplicationFinalize.js.map +1 -1
  32. package/lib/internal/_llmApplicationFinalize.mjs +1 -1
  33. package/lib/internal/_llmApplicationFinalize.mjs.map +1 -1
  34. package/lib/internal/_randomFormatByte.js +24 -1
  35. package/lib/internal/_randomFormatByte.js.map +1 -1
  36. package/lib/internal/_randomFormatByte.mjs +20 -2
  37. package/lib/internal/_randomFormatByte.mjs.map +1 -1
  38. package/lib/internal/_randomFormatDate.d.ts +3 -6
  39. package/lib/internal/_randomFormatDate.js +2 -10
  40. package/lib/internal/_randomFormatDate.js.map +1 -1
  41. package/lib/internal/_randomFormatDate.mjs +2 -6
  42. package/lib/internal/_randomFormatDate.mjs.map +1 -1
  43. package/lib/internal/_randomFormatDatetime.d.ts +3 -6
  44. package/lib/internal/_randomFormatDatetime.js +25 -8
  45. package/lib/internal/_randomFormatDatetime.js.map +1 -1
  46. package/lib/internal/_randomFormatDatetime.mjs +17 -7
  47. package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
  48. package/lib/internal/_randomFormatDuration.js +23 -15
  49. package/lib/internal/_randomFormatDuration.js.map +1 -1
  50. package/lib/internal/_randomFormatDuration.mjs +23 -15
  51. package/lib/internal/_randomFormatDuration.mjs.map +1 -1
  52. package/lib/internal/_randomFormatIpv4.js +31 -1
  53. package/lib/internal/_randomFormatIpv4.js.map +1 -1
  54. package/lib/internal/_randomFormatIpv4.mjs +23 -2
  55. package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
  56. package/lib/internal/_randomFormatIpv6.js +57 -1
  57. package/lib/internal/_randomFormatIpv6.js.map +1 -1
  58. package/lib/internal/_randomFormatIpv6.mjs +45 -2
  59. package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
  60. package/lib/internal/_randomFormatJsonPointer.js +14 -2
  61. package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
  62. package/lib/internal/_randomFormatJsonPointer.mjs +13 -3
  63. package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
  64. package/lib/internal/_randomFormatRegex.js +14 -1
  65. package/lib/internal/_randomFormatRegex.js.map +1 -1
  66. package/lib/internal/_randomFormatRegex.mjs +14 -2
  67. package/lib/internal/_randomFormatRegex.mjs.map +1 -1
  68. package/lib/internal/_randomFormatRelativeJsonPointer.js +19 -5
  69. package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
  70. package/lib/internal/_randomFormatRelativeJsonPointer.mjs +21 -6
  71. package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
  72. package/lib/internal/_randomFormatTime.js +33 -7
  73. package/lib/internal/_randomFormatTime.js.map +1 -1
  74. package/lib/internal/_randomFormatTime.mjs +37 -5
  75. package/lib/internal/_randomFormatTime.mjs.map +1 -1
  76. package/lib/internal/_randomPattern.js.map +1 -1
  77. package/lib/internal/_randomPattern.mjs.map +1 -1
  78. package/lib/internal/_randomStringLength.d.ts +41 -10
  79. package/lib/internal/_randomStringLength.js +49 -13
  80. package/lib/internal/_randomStringLength.js.map +1 -1
  81. package/lib/internal/_randomStringLength.mjs +48 -13
  82. package/lib/internal/_randomStringLength.mjs.map +1 -1
  83. package/lib/internal/private/__notationRename.js.map +1 -1
  84. package/lib/internal/private/__notationRename.mjs.map +1 -1
  85. package/lib/internal/private/__randomComposition.d.ts +23 -0
  86. package/lib/internal/private/__randomComposition.js +48 -0
  87. package/lib/internal/private/__randomComposition.js.map +1 -0
  88. package/lib/internal/private/__randomComposition.mjs +54 -0
  89. package/lib/internal/private/__randomComposition.mjs.map +1 -0
  90. package/lib/internal/private/__randomEpoch.d.ts +19 -0
  91. package/lib/internal/private/__randomEpoch.js +31 -0
  92. package/lib/internal/private/__randomEpoch.js.map +1 -0
  93. package/lib/internal/private/__randomEpoch.mjs +28 -0
  94. package/lib/internal/private/__randomEpoch.mjs.map +1 -0
  95. package/native/cmd/ttsc-typia/build.go +3 -0
  96. package/native/cmd/ttsc-typia/callable_interface_function_semantics_transform_test.go +331 -0
  97. package/native/cmd/ttsc-typia/callable_type_literal_boundaries_transform_test.go +1184 -0
  98. package/native/cmd/ttsc-typia/compare_functional_union_membership_transform_test.go +434 -0
  99. package/native/cmd/ttsc-typia/compare_template_literal_union_transform_test.go +241 -0
  100. package/native/cmd/ttsc-typia/default_library_spoof_native_identity_transform_test.go +216 -0
  101. package/native/cmd/ttsc-typia/json_schema_dynamic_key_determinism_transform_test.go +246 -0
  102. package/native/cmd/ttsc-typia/json_stringify_contextual_undefined_transform_test.go +556 -0
  103. package/native/cmd/ttsc-typia/lib_replacement_native_identity_transform_test.go +277 -0
  104. package/native/cmd/ttsc-typia/native_named_intersection_union_transform_test.go +390 -0
  105. package/native/cmd/ttsc-typia/node_buffer_native_exports_is_transform_test.go +526 -0
  106. package/native/cmd/ttsc-typia/package_declaration_native_identity_is_transform_test.go +293 -0
  107. package/native/cmd/ttsc-typia/protobuf_diagnostic_code_transform_test.go +167 -0
  108. package/native/cmd/ttsc-typia/symbol_index_domain_transform_test.go +316 -0
  109. package/native/cmd/ttsc-typia/transform.go +23 -0
  110. package/native/cmd/ttsc-typia/transform_helpers_test.go +77 -2
  111. package/native/cmd/ttsc-typia/user_global_native_identity_transform_test.go +484 -0
  112. package/native/core/factories/ProtobufFactory.go +6 -1
  113. package/native/core/factories/internal/metadata/MetadataHelper.go +185 -30
  114. package/native/core/factories/internal/metadata/emplace_metadata_object.go +25 -0
  115. package/native/core/factories/internal/metadata/iterate_metadata_function.go +1 -1
  116. package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +103 -23
  117. package/native/core/factories/internal/metadata/iterate_metadata_map.go +3 -7
  118. package/native/core/factories/internal/metadata/iterate_metadata_native.go +32 -14
  119. package/native/core/factories/internal/metadata/iterate_metadata_set.go +3 -7
  120. package/native/core/programmers/compare/CompareEqualProgrammer.go +27 -13
  121. package/native/core/programmers/helpers/FunctionProgrammer.go +6 -13
  122. package/native/core/programmers/helpers/StringifyJoinder.go +129 -50
  123. package/native/core/programmers/helpers/joiner_branch_coverage_test.go +116 -120
  124. package/native/core/programmers/iterate/iterate_check_coverage_test.go +76 -158
  125. package/native/core/programmers/iterate/iterate_utility_coverage_test.go +231 -270
  126. package/native/core/programmers/iterate/json_schema_object.go +49 -7
  127. package/native/core/programmers/iterate/json_schema_pattern_property_order_test.go +44 -0
  128. package/native/core/programmers/iterate/openapi_v3_downgrader.go +34 -1
  129. package/native/core/programmers/iterate/template_runtime_pattern.go +11 -0
  130. package/native/core/programmers/json/JsonStringifyProgrammer.go +47 -6
  131. package/native/core/programmers/llm/LlmApplicationProgrammer.go +9 -1
  132. package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +1 -1
  133. package/native/core/schemas/metadata/MetadataCollection.go +0 -9
  134. package/native/core/schemas/metadata/MetadataDefaultLibrary.go +81 -0
  135. package/native/core/schemas/metadata/MetadataObjectType.go +7 -18
  136. package/native/go.mod +4 -4
  137. package/native/transform/features/protobuf/ProtobufMessageTransformer.go +1 -1
  138. package/package.json +3 -7
  139. package/src/executable/FileSystemIdentity.ts +33 -0
  140. package/src/executable/TypiaGenerateWizard.ts +18 -12
  141. package/src/internal/_ProtobufReader.ts +40 -11
  142. package/src/internal/_jsonStringifyArray.ts +50 -0
  143. package/src/internal/_jsonStringifyElement.ts +19 -0
  144. package/src/internal/_jsonStringifyProperty.ts +30 -0
  145. package/src/internal/_llmApplicationFinalize.ts +6 -1
  146. package/src/internal/_randomFormatByte.ts +30 -3
  147. package/src/internal/_randomFormatDate.ts +4 -20
  148. package/src/internal/_randomFormatDatetime.ts +34 -20
  149. package/src/internal/_randomFormatDuration.ts +19 -4
  150. package/src/internal/_randomFormatIpv4.ts +43 -3
  151. package/src/internal/_randomFormatIpv6.ts +67 -3
  152. package/src/internal/_randomFormatJsonPointer.ts +23 -3
  153. package/src/internal/_randomFormatRegex.ts +21 -3
  154. package/src/internal/_randomFormatRelativeJsonPointer.ts +23 -10
  155. package/src/internal/_randomFormatTime.ts +45 -12
  156. package/src/internal/_randomPattern.ts +4 -1
  157. package/src/internal/_randomStringLength.ts +61 -17
  158. package/src/internal/private/__notationRename.ts +1 -4
  159. package/src/internal/private/__randomComposition.ts +50 -0
  160. package/src/internal/private/__randomEpoch.ts +34 -0
  161. package/native/adapter/visit.go +0 -173
  162. package/native/adapter/visit_property_chain_edges_test.go +0 -129
  163. package/native/core/programmers/helpers/disable_function_programmer_declare.go +0 -10
  164. package/native/core/programmers/iterate/check_union_array_like.go +0 -422
  165. package/native/core/programmers/iterate/prune_object_properties.go +0 -105
  166. package/native/core/programmers/iterate/stringify_dynamic_properties.go +0 -219
  167. package/native/core/programmers/iterate/stringify_native.go +0 -14
  168. package/native/core/programmers/iterate/stringify_regular_properties.go +0 -112
  169. package/native/core/schemas/metadata/MetadataApplication.go +0 -41
@@ -1,5 +1,9 @@
1
+ import { _randomInteger } from "./_randomInteger";
1
2
  import { _randomString } from "./_randomString";
2
3
 
4
+ export const _RANDOM_LENGTH_ERROR =
5
+ "unable to generate a random string satisfying both the format and the length constraints.";
6
+
3
7
  /**
4
8
  * Length bounds forwarded to a string format or pattern generator.
5
9
  *
@@ -18,10 +22,10 @@ export interface _ILengthProps {
18
22
  * length `fixed + segment.length` lands inside the requested window.
19
23
  *
20
24
  * `fixed` is the number of characters the format always contributes around the
21
- * segment, `fallback` is the segment length used when the leaf is
22
- * unconstrained on that side, and `minimum` is the smallest segment the format
23
- * still validates with. Throws when the window cannot be satisfied by this
24
- * format's shape (e.g. `Format<"email"> & MaxLength<3>`).
25
+ * segment, `fallback` is the segment length used when the leaf is unconstrained
26
+ * on that side, and `minimum` is the smallest segment the format still
27
+ * validates with. Throws when the window cannot be satisfied by this format's
28
+ * shape (e.g. `Format<"email"> & MaxLength<3>`).
25
29
  */
26
30
  export const _randomSegmentLength = (
27
31
  props: _ILengthProps | undefined,
@@ -36,21 +40,63 @@ export const _randomSegmentLength = (
36
40
  // characters so the generated length varies, mirroring `_randomString`.
37
41
  const high: number =
38
42
  props?.maxLength === undefined ? low + fallback : props.maxLength - fixed;
39
- if (high < low || high < minimum)
40
- throw new Error(
41
- "unable to generate a random string satisfying both the format and the length constraints.",
42
- );
43
+ if (high < low || high < minimum) throw new Error(_RANDOM_LENGTH_ERROR);
43
44
  return _randomString({ type: "string", minLength: low, maxLength: high });
44
45
  };
45
46
 
46
47
  /**
47
- * Wraps a fixed- or narrow-length format generator (uuid, ipv4, date, ...) with
48
- * the requested length window.
48
+ * Intersects the requested length window with the lengths a format's grammar
49
+ * can express, and draws one of them.
50
+ *
51
+ * `minimum` and `maximum` are the shortest and longest values the format admits
52
+ * — omit `maximum` when the grammar is open above — and `spread` is how far
53
+ * past the floor an unbounded request may reach, so an open side still varies
54
+ * the way `_randomString` does. The caller draws from the returned window and
55
+ * applies whatever step its grammar has (base64 lengths are multiples of four,
56
+ * a fractional second needs at least one digit).
57
+ *
58
+ * Throws only when the window and the grammar do not overlap at all. That is
59
+ * the distinction the retry driver below cannot make: it redraws one shape, so
60
+ * it gives up on every length that shape never emits even when the format
61
+ * itself accepts one (issue #2284).
62
+ */
63
+ export const _randomLengthWindow = (
64
+ props: _ILengthProps | undefined,
65
+ format: { minimum: number; maximum?: number; spread?: number },
66
+ ): { low: number; high: number } => {
67
+ const ceiling: number = format.maximum ?? Number.MAX_SAFE_INTEGER;
68
+ const low: number = Math.max(
69
+ props?.minLength ?? format.minimum,
70
+ format.minimum,
71
+ );
72
+ const high: number = Math.min(
73
+ props?.maxLength ?? low + (format.spread ?? 0),
74
+ ceiling,
75
+ );
76
+ if (low > high) throw new Error(_RANDOM_LENGTH_ERROR);
77
+ return { low, high };
78
+ };
79
+
80
+ /** Draws a length inside a window produced by {@link _randomLengthWindow}. */
81
+ export const _randomLengthPick = (window: {
82
+ low: number;
83
+ high: number;
84
+ }): number =>
85
+ _randomInteger({
86
+ type: "integer",
87
+ minimum: window.low,
88
+ maximum: window.high,
89
+ });
90
+
91
+ /**
92
+ * Wraps a fixed-length format generator (uuid, date) with the requested length
93
+ * window.
49
94
  *
50
- * These formats cannot grow an arbitrary segment, so the generator is retried a
51
- * bounded number of times and the first draw inside the window is returned. A
52
- * window that excludes every length the format can produce is unsatisfiable and
53
- * throws instead of silently yielding an out-of-range value.
95
+ * Use it only where the grammar admits exactly one length, so a window that
96
+ * excludes it is genuinely unsatisfiable. A format that can express more than
97
+ * one length must build its value at a length drawn from
98
+ * {@link _randomLengthWindow} instead; redrawing one shape cannot reach a length
99
+ * that shape never emits.
54
100
  */
55
101
  export const _randomFormatLength = (
56
102
  props: _ILengthProps | undefined,
@@ -66,7 +112,5 @@ export const _randomFormatLength = (
66
112
  )
67
113
  return value;
68
114
  }
69
- throw new Error(
70
- "unable to generate a random string satisfying both the format and the length constraints.",
71
- );
115
+ throw new Error(_RANDOM_LENGTH_ERROR);
72
116
  };
@@ -9,10 +9,7 @@
9
9
  * collapsing it to the underscore-free `plain` path.
10
10
  */
11
11
  export const __notationRename =
12
- (props: {
13
- plain: (str: string) => string;
14
- snake: (str: string) => string;
15
- }) =>
12
+ (props: { plain: (str: string) => string; snake: (str: string) => string }) =>
16
13
  (str: string): string => {
17
14
  let prefix: string = "";
18
15
  while (str.startsWith("_")) {
@@ -0,0 +1,50 @@
1
+ import { _randomInteger } from "../_randomInteger";
2
+
3
+ /**
4
+ * Splits `total` into `count` parts, each inside `[minimum, maximum]`.
5
+ *
6
+ * Used where a format's length is the sum of its segments — an IPv4 octet spans
7
+ * one to three digits, an IPv6 group one to four — so a requested total length
8
+ * is realized by choosing how many characters each segment contributes instead
9
+ * of redrawing whole addresses and hoping one lands in the window (issue
10
+ * #2284).
11
+ *
12
+ * The caller guarantees `count * minimum <= total <= count * maximum`; each
13
+ * part is drawn from the range that still leaves the remaining parts
14
+ * satisfiable.
15
+ */
16
+ export const __randomComposition = (props: {
17
+ total: number;
18
+ count: number;
19
+ minimum: number;
20
+ maximum: number;
21
+ }): number[] => {
22
+ const parts: number[] = [];
23
+ let remaining: number = props.total;
24
+ for (let i: number = 0; i < props.count; ++i) {
25
+ const rest: number = props.count - i - 1;
26
+ const value: number = _randomInteger({
27
+ type: "integer",
28
+ minimum: Math.max(props.minimum, remaining - rest * props.maximum),
29
+ maximum: Math.min(props.maximum, remaining - rest * props.minimum),
30
+ });
31
+ parts.push(value);
32
+ remaining -= value;
33
+ }
34
+ return parts;
35
+ };
36
+
37
+ /** Draws `length` decimal digits, leading zeros included. */
38
+ export const __randomDigits = (length: number): string => {
39
+ let text: string = "";
40
+ for (let i: number = 0; i < length; ++i)
41
+ text += String(_randomInteger({ type: "integer", minimum: 0, maximum: 9 }));
42
+ return text;
43
+ };
44
+
45
+ /** Draws a decimal number of exactly `length` digits without a leading zero. */
46
+ export const __randomNumeric = (length: number): string =>
47
+ length <= 1
48
+ ? String(_randomInteger({ type: "integer", minimum: 0, maximum: 9 }))
49
+ : String(_randomInteger({ type: "integer", minimum: 1, maximum: 9 })) +
50
+ __randomDigits(length - 1);
@@ -0,0 +1,34 @@
1
+ import { _randomInteger } from "../_randomInteger";
2
+
3
+ export interface __IEpochProps {
4
+ minimum?: number;
5
+ maximum?: number;
6
+ }
7
+
8
+ /**
9
+ * Draws an epoch millisecond inside the requested bounds.
10
+ *
11
+ * Shared by the `date` and `date-time` generators, which had the same bound
12
+ * expression written twice: `props?.maximum ?? props?.minimum === undefined`
13
+ * parses as `props?.maximum ?? (props?.minimum === undefined)` because `??`
14
+ * binds looser than `===`, so any supplied `maximum` made the condition truthy
15
+ * and was replaced by `Date.now()`, while `maximum: 0` fell through to
16
+ * `undefined + one year` and produced `NaN` (issue #2287). Keeping the
17
+ * resolution in one place is what stops the two copies from drifting again.
18
+ *
19
+ * With no bound at all the window ends at the present instant; with only a
20
+ * lower bound it spans one year from there.
21
+ */
22
+ export const __randomEpoch = (props?: __IEpochProps): number => {
23
+ const minimum: number = props?.minimum ?? 0;
24
+ const maximum: number =
25
+ props?.maximum ??
26
+ (props?.minimum === undefined ? Date.now() : props.minimum + YEAR);
27
+ return _randomInteger({
28
+ type: "integer",
29
+ minimum,
30
+ maximum,
31
+ });
32
+ };
33
+
34
+ const YEAR = 365 * 24 * 60 * 60 * 1_000;
@@ -1,173 +0,0 @@
1
- package adapter
2
-
3
- import (
4
- "path/filepath"
5
- "strings"
6
-
7
- shimast "github.com/microsoft/typescript-go/shim/ast"
8
- shimchecker "github.com/microsoft/typescript-go/shim/checker"
9
- )
10
-
11
- type CallSite struct {
12
- File *shimast.SourceFile
13
- FilePath string
14
- Module string
15
- Method string
16
- Call *shimast.CallExpression
17
- RootName string
18
- Namespaces []string
19
- }
20
-
21
- func CollectCallSites(files []*shimast.SourceFile, checker *shimchecker.Checker) []CallSite {
22
- sites := []CallSite{}
23
- for _, file := range files {
24
- if file == nil || file.IsDeclarationFile {
25
- continue
26
- }
27
- file.ForEachChild(func(node *shimast.Node) bool {
28
- visitCallSite(file, checker, node, &sites)
29
- return false
30
- })
31
- }
32
- return sites
33
- }
34
-
35
- func visitCallSite(file *shimast.SourceFile, checker *shimchecker.Checker, node *shimast.Node, sites *[]CallSite) {
36
- if node == nil {
37
- return
38
- }
39
- if node.Kind == shimast.KindCallExpression {
40
- if site, ok := tryCallSite(file, checker, node); ok {
41
- *sites = append(*sites, site)
42
- }
43
- }
44
- node.ForEachChild(func(child *shimast.Node) bool {
45
- visitCallSite(file, checker, child, sites)
46
- return false
47
- })
48
- }
49
-
50
- func tryCallSite(file *shimast.SourceFile, checker *shimchecker.Checker, node *shimast.Node) (CallSite, bool) {
51
- if checker == nil {
52
- return CallSite{}, false
53
- }
54
- if node.Kind != shimast.KindCallExpression {
55
- return CallSite{}, false
56
- }
57
- call := node.AsCallExpression()
58
- if call == nil {
59
- return CallSite{}, false
60
- }
61
- signature := checker.GetResolvedSignature(node)
62
- if signature == nil {
63
- return CallSite{}, false
64
- }
65
- declaration := signature.Declaration()
66
- if declaration == nil {
67
- return CallSite{}, false
68
- }
69
- sourceFile := shimast.GetSourceFileOfNode(declaration)
70
- if sourceFile == nil {
71
- return CallSite{}, false
72
- }
73
- module, ok := matchTypiaModule(sourceFile.FileName())
74
- if !ok {
75
- return CallSite{}, false
76
- }
77
- method := callSiteMethodName(checker, declaration, call)
78
- if method == "" {
79
- return CallSite{}, false
80
- }
81
- root, namespaces, ok := extractRootAndNamespaces(call, method)
82
- if !ok {
83
- return CallSite{}, false
84
- }
85
- return CallSite{
86
- File: file,
87
- FilePath: file.FileName(),
88
- Module: module,
89
- Method: method,
90
- Call: call,
91
- RootName: root,
92
- Namespaces: namespaces,
93
- }, true
94
- }
95
-
96
- func matchTypiaModule(location string) (string, bool) {
97
- location = filepath.ToSlash(location)
98
- for _, suffix := range []string{".d.ts", ".ts"} {
99
- for _, middle := range []string{"typia/lib/", "typia/src/", "packages/typia/src/"} {
100
- index := strings.LastIndex(location, middle)
101
- if index < 0 {
102
- continue
103
- }
104
- name := location[index+len(middle):]
105
- if !strings.HasSuffix(name, suffix) {
106
- continue
107
- }
108
- name = strings.TrimSuffix(name, suffix)
109
- if strings.Contains(name, "/") {
110
- continue
111
- }
112
- return name, true
113
- }
114
- }
115
- return "", false
116
- }
117
-
118
- func callSiteMethodName(checker *shimchecker.Checker, declaration *shimast.Node, call *shimast.CallExpression) string {
119
- if name := declaration.Name(); name != nil {
120
- if checker != nil {
121
- if symbol := checker.GetSymbolAtLocation(name); symbol != nil && symbol.Name != "" {
122
- return symbol.Name
123
- }
124
- }
125
- if name.Kind == shimast.KindIdentifier {
126
- if id := name.AsIdentifier(); id != nil {
127
- return id.Text
128
- }
129
- }
130
- }
131
- if call.Expression != nil && call.Expression.Kind == shimast.KindPropertyAccessExpression {
132
- if property := call.Expression.AsPropertyAccessExpression(); property != nil {
133
- if name := property.Name(); name != nil && name.Kind == shimast.KindIdentifier {
134
- if id := name.AsIdentifier(); id != nil {
135
- return id.Text
136
- }
137
- }
138
- }
139
- }
140
- return ""
141
- }
142
-
143
- func extractRootAndNamespaces(call *shimast.CallExpression, method string) (string, []string, bool) {
144
- expression := call.Expression
145
- segments := []string{}
146
- for expression != nil && expression.Kind == shimast.KindPropertyAccessExpression {
147
- property := expression.AsPropertyAccessExpression()
148
- if property == nil {
149
- break
150
- }
151
- name := property.Name()
152
- if name == nil || name.Kind != shimast.KindIdentifier {
153
- return "", nil, false
154
- }
155
- id := name.AsIdentifier()
156
- if id == nil || id.Text == "" {
157
- return "", nil, false
158
- }
159
- segments = append([]string{id.Text}, segments...)
160
- expression = property.Expression
161
- }
162
- if expression == nil || expression.Kind != shimast.KindIdentifier {
163
- return "", nil, false
164
- }
165
- root := expression.AsIdentifier()
166
- if root == nil || root.Text == "" || len(segments) == 0 {
167
- return "", nil, false
168
- }
169
- if segments[len(segments)-1] != method {
170
- return "", nil, false
171
- }
172
- return root.Text, segments[:len(segments)-1], true
173
- }
@@ -1,129 +0,0 @@
1
- //go:build typia_native_internal
2
- // +build typia_native_internal
3
-
4
- package adapter
5
-
6
- import (
7
- "path/filepath"
8
- "testing"
9
-
10
- shimast "github.com/microsoft/typescript-go/shim/ast"
11
- shimchecker "github.com/microsoft/typescript-go/shim/checker"
12
- shimcore "github.com/microsoft/typescript-go/shim/core"
13
- shimparser "github.com/microsoft/typescript-go/shim/parser"
14
- )
15
-
16
- // TestVisitPropertyChainEdges verifies call-site property-chain parsing.
17
- //
18
- // Call-site discovery peels a TypeScript expression like
19
- // `typia.json.stringify()` into a root import name, namespace chain, and method.
20
- // Malformed or mismatched chains must be rejected without producing a site.
21
- //
22
- // 1. Build a nested property-access call expression.
23
- // 2. Extract the root name, namespace, and terminal method.
24
- // 3. Reject a method mismatch, a non-property call, and an empty member name.
25
- // 4. Verify nil nodes do not append call sites.
26
- func TestVisitPropertyChainEdges(t *testing.T) {
27
- factory := shimast.NewNodeFactory(shimast.NodeFactoryHooks{})
28
- namespace := factory.NewPropertyAccessExpression(
29
- factory.NewIdentifier("typia"),
30
- nil,
31
- factory.NewIdentifier("json"),
32
- shimast.NodeFlagsNone,
33
- )
34
- method := factory.NewPropertyAccessExpression(
35
- namespace,
36
- nil,
37
- factory.NewIdentifier("stringify"),
38
- shimast.NodeFlagsNone,
39
- )
40
- call := factory.NewCallExpression(method, nil, nil, factory.NewNodeList(nil), shimast.NodeFlagsNone).AsCallExpression()
41
-
42
- root, namespaces, ok := extractRootAndNamespaces(call, "stringify")
43
- if !ok || root != "typia" || len(namespaces) != 1 || namespaces[0] != "json" {
44
- t.Fatalf("unexpected property-chain extraction: root=%q namespaces=%#v ok=%v", root, namespaces, ok)
45
- }
46
- if _, _, ok := extractRootAndNamespaces(call, "is"); ok {
47
- t.Fatal("method mismatch should reject the call chain")
48
- }
49
- statement := factory.NewExpressionStatement(factory.NewIdentifier("noop"))
50
- if method := callSiteMethodName(nil, statement, call); method != "stringify" {
51
- t.Fatalf("property-access method fallback mismatch: %q", method)
52
- }
53
- declaration := factory.NewFunctionDeclaration(
54
- nil,
55
- nil,
56
- factory.NewIdentifier("declared"),
57
- nil,
58
- nil,
59
- nil,
60
- nil,
61
- nil,
62
- )
63
- if method := callSiteMethodName(nil, declaration, call); method != "declared" {
64
- t.Fatalf("declaration-name fallback mismatch: %q", method)
65
- }
66
-
67
- plain := factory.NewCallExpression(
68
- factory.NewIdentifier("plain"),
69
- nil,
70
- nil,
71
- factory.NewNodeList(nil),
72
- shimast.NodeFlagsNone,
73
- ).AsCallExpression()
74
- if _, _, ok := extractRootAndNamespaces(plain, "plain"); ok {
75
- t.Fatal("plain calls without a property chain should be rejected")
76
- }
77
- literal := factory.NewCallExpression(
78
- factory.NewStringLiteral("call", shimast.TokenFlagsNone),
79
- nil,
80
- nil,
81
- factory.NewNodeList(nil),
82
- shimast.NodeFlagsNone,
83
- ).AsCallExpression()
84
- if _, _, ok := extractRootAndNamespaces(literal, "call"); ok {
85
- t.Fatal("non-identifier root expressions should be rejected")
86
- }
87
-
88
- emptyMember := factory.NewPropertyAccessExpression(
89
- factory.NewIdentifier("typia"),
90
- nil,
91
- factory.NewIdentifier(""),
92
- shimast.NodeFlagsNone,
93
- )
94
- emptyCall := factory.NewCallExpression(emptyMember, nil, nil, factory.NewNodeList(nil), shimast.NodeFlagsNone).AsCallExpression()
95
- if _, _, ok := extractRootAndNamespaces(emptyCall, ""); ok {
96
- t.Fatal("empty property name should be rejected")
97
- }
98
- stringMember := factory.NewPropertyAccessExpression(
99
- factory.NewIdentifier("typia"),
100
- nil,
101
- factory.NewStringLiteral("is", shimast.TokenFlagsNone),
102
- shimast.NodeFlagsNone,
103
- )
104
- stringMemberCall := factory.NewCallExpression(stringMember, nil, nil, factory.NewNodeList(nil), shimast.NodeFlagsNone).AsCallExpression()
105
- if _, _, ok := extractRootAndNamespaces(stringMemberCall, "is"); ok {
106
- t.Fatal("non-identifier property names should be rejected")
107
- }
108
- sites := []CallSite{}
109
- visitCallSite(nil, nil, nil, &sites)
110
- if len(sites) != 0 {
111
- t.Fatalf("nil node should not append call sites: %#v", sites)
112
- }
113
- file := shimparser.ParseSourceFile(
114
- shimast.SourceFileParseOptions{FileName: filepath.ToSlash(filepath.Join(t.TempDir(), "visit.ts"))},
115
- `typia.is(input);`,
116
- shimcore.ScriptKindTS,
117
- )
118
- declFile := *file
119
- declFile.IsDeclarationFile = true
120
- if sites := CollectCallSites([]*shimast.SourceFile{nil, &declFile}, nil); len(sites) != 0 {
121
- t.Fatalf("nil and declaration files should not produce call sites: %#v", sites)
122
- }
123
- if _, ok := tryCallSite(file, nil, call.AsNode()); ok {
124
- t.Fatal("nil checker should reject call-site probing")
125
- }
126
- if _, ok := tryCallSite(file, &shimchecker.Checker{}, statement); ok {
127
- t.Fatal("non-call nodes should reject call-site probing")
128
- }
129
- }
@@ -1,10 +0,0 @@
1
- package helpers
2
-
3
- func Disable_function_programmer_declare(functor *FunctionProgrammer) *FunctionProgrammer {
4
- if functor == nil {
5
- return nil
6
- }
7
- disabled := *functor
8
- disabled.disableDeclare = true
9
- return &disabled
10
- }