typia 13.1.19 → 13.3.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.
- package/lib/executable/FileSystemIdentity.d.ts +23 -0
- package/lib/executable/FileSystemIdentity.js +30 -0
- package/lib/executable/FileSystemIdentity.js.map +1 -1
- package/lib/executable/FileSystemIdentity.mjs +4 -0
- package/lib/executable/FileSystemIdentity.mjs.map +1 -1
- package/lib/executable/TypiaGenerateWizard.js +15 -9
- package/lib/executable/TypiaGenerateWizard.js.map +1 -1
- package/lib/executable/TypiaGenerateWizard.mjs +11 -7
- package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
- package/lib/http.d.ts +3 -3
- package/lib/http.js.map +1 -1
- package/lib/http.mjs.map +1 -1
- package/lib/internal/_ProtobufReader.d.ts +18 -3
- package/lib/internal/_ProtobufReader.js +39 -11
- package/lib/internal/_ProtobufReader.js.map +1 -1
- package/lib/internal/_ProtobufReader.mjs +37 -10
- package/lib/internal/_ProtobufReader.mjs.map +1 -1
- package/lib/internal/_assertGuard.js +13 -3
- package/lib/internal/_assertGuard.js.map +1 -1
- package/lib/internal/_assertGuard.mjs +4 -2
- package/lib/internal/_assertGuard.mjs.map +1 -1
- package/lib/internal/_isFormatIdnHostname.js +5 -1
- package/lib/internal/_isFormatIdnHostname.js.map +1 -1
- package/lib/internal/_isFormatIdnHostname.mjs +1 -1
- package/lib/internal/_isFormatIdnHostname.mjs.map +1 -1
- package/lib/internal/_isFormatTime.js +19 -2
- package/lib/internal/_isFormatTime.js.map +1 -1
- package/lib/internal/_isFormatTime.mjs +9 -2
- package/lib/internal/_isFormatTime.mjs.map +1 -1
- package/lib/internal/_jsonStringifyArray.d.ts +1 -0
- package/lib/internal/_jsonStringifyArray.js +48 -0
- package/lib/internal/_jsonStringifyArray.js.map +1 -0
- package/lib/internal/_jsonStringifyArray.mjs +40 -0
- package/lib/internal/_jsonStringifyArray.mjs.map +1 -0
- package/lib/internal/_jsonStringifyElement.d.ts +1 -0
- package/lib/internal/_jsonStringifyElement.js +23 -0
- package/lib/internal/_jsonStringifyElement.js.map +1 -0
- package/lib/internal/_jsonStringifyElement.mjs +23 -0
- package/lib/internal/_jsonStringifyElement.mjs.map +1 -0
- package/lib/internal/_jsonStringifyProperty.d.ts +1 -0
- package/lib/internal/_jsonStringifyProperty.js +31 -0
- package/lib/internal/_jsonStringifyProperty.js.map +1 -0
- package/lib/internal/_jsonStringifyProperty.mjs +31 -0
- package/lib/internal/_jsonStringifyProperty.mjs.map +1 -0
- package/lib/internal/_llmApplicationFinalize.js +1 -1
- package/lib/internal/_llmApplicationFinalize.js.map +1 -1
- package/lib/internal/_llmApplicationFinalize.mjs +1 -1
- package/lib/internal/_llmApplicationFinalize.mjs.map +1 -1
- package/lib/internal/_randomArray.js +37 -4
- package/lib/internal/_randomArray.js.map +1 -1
- package/lib/internal/_randomArray.mjs +16 -3
- package/lib/internal/_randomArray.mjs.map +1 -1
- package/lib/internal/_randomFormatByte.js +28 -2
- package/lib/internal/_randomFormatByte.js.map +1 -1
- package/lib/internal/_randomFormatByte.mjs +22 -3
- package/lib/internal/_randomFormatByte.mjs.map +1 -1
- package/lib/internal/_randomFormatDate.d.ts +3 -6
- package/lib/internal/_randomFormatDate.js +2 -10
- package/lib/internal/_randomFormatDate.js.map +1 -1
- package/lib/internal/_randomFormatDate.mjs +2 -6
- package/lib/internal/_randomFormatDate.mjs.map +1 -1
- package/lib/internal/_randomFormatDatetime.d.ts +3 -6
- package/lib/internal/_randomFormatDatetime.js +25 -8
- package/lib/internal/_randomFormatDatetime.js.map +1 -1
- package/lib/internal/_randomFormatDatetime.mjs +17 -7
- package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
- package/lib/internal/_randomFormatDuration.js +23 -15
- package/lib/internal/_randomFormatDuration.js.map +1 -1
- package/lib/internal/_randomFormatDuration.mjs +23 -15
- package/lib/internal/_randomFormatDuration.mjs.map +1 -1
- package/lib/internal/_randomFormatHostname.d.ts +2 -2
- package/lib/internal/_randomFormatHostname.js +2 -2
- package/lib/internal/_randomFormatHostname.mjs +2 -2
- package/lib/internal/_randomFormatHostname.mjs.map +1 -1
- package/lib/internal/_randomFormatIdnHostname.js +9 -10
- package/lib/internal/_randomFormatIdnHostname.js.map +1 -1
- package/lib/internal/_randomFormatIdnHostname.mjs +3 -4
- package/lib/internal/_randomFormatIdnHostname.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv4.js +31 -1
- package/lib/internal/_randomFormatIpv4.js.map +1 -1
- package/lib/internal/_randomFormatIpv4.mjs +23 -2
- package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv6.js +57 -1
- package/lib/internal/_randomFormatIpv6.js.map +1 -1
- package/lib/internal/_randomFormatIpv6.mjs +45 -2
- package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.js +14 -2
- package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.mjs +13 -3
- package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatRegex.js +15 -2
- package/lib/internal/_randomFormatRegex.js.map +1 -1
- package/lib/internal/_randomFormatRegex.mjs +14 -3
- package/lib/internal/_randomFormatRegex.mjs.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.js +19 -5
- package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs +21 -6
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatTime.js +38 -7
- package/lib/internal/_randomFormatTime.js.map +1 -1
- package/lib/internal/_randomFormatTime.mjs +40 -5
- package/lib/internal/_randomFormatTime.mjs.map +1 -1
- package/lib/internal/_randomPattern.js.map +1 -1
- package/lib/internal/_randomPattern.mjs.map +1 -1
- package/lib/internal/_randomStringLength.d.ts +41 -10
- package/lib/internal/_randomStringLength.js +49 -13
- package/lib/internal/_randomStringLength.js.map +1 -1
- package/lib/internal/_randomStringLength.mjs +48 -13
- package/lib/internal/_randomStringLength.mjs.map +1 -1
- package/lib/internal/private/__notationRename.js.map +1 -1
- package/lib/internal/private/__notationRename.mjs.map +1 -1
- package/lib/internal/private/__randomComposition.d.ts +31 -0
- package/lib/internal/private/__randomComposition.js +68 -0
- package/lib/internal/private/__randomComposition.js.map +1 -0
- package/lib/internal/private/__randomComposition.mjs +71 -0
- package/lib/internal/private/__randomComposition.mjs.map +1 -0
- package/lib/internal/private/__randomEpoch.d.ts +19 -0
- package/lib/internal/private/__randomEpoch.js +31 -0
- package/lib/internal/private/__randomEpoch.js.map +1 -0
- package/lib/internal/private/__randomEpoch.mjs +28 -0
- package/lib/internal/private/__randomEpoch.mjs.map +1 -0
- package/lib/json.d.ts +2 -2
- package/lib/json.js.map +1 -1
- package/lib/json.mjs.map +1 -1
- package/lib/module.d.ts +28 -13
- package/lib/module.js.map +1 -1
- package/lib/module.mjs.map +1 -1
- package/lib/notations.d.ts +4 -4
- package/lib/notations.js.map +1 -1
- package/lib/notations.mjs.map +1 -1
- package/lib/plain.d.ts +3 -3
- package/lib/plain.js.map +1 -1
- package/lib/plain.mjs.map +1 -1
- package/lib/protobuf.d.ts +2 -2
- package/lib/protobuf.js.map +1 -1
- package/lib/protobuf.mjs.map +1 -1
- package/native/cmd/ttsc-typia/assert_guard_factory_contract_test.go +17 -4
- package/native/cmd/ttsc-typia/build.go +3 -0
- package/native/cmd/ttsc-typia/callable_interface_function_semantics_transform_test.go +331 -0
- package/native/cmd/ttsc-typia/callable_type_literal_boundaries_transform_test.go +1184 -0
- package/native/cmd/ttsc-typia/compare_functional_union_membership_transform_test.go +434 -0
- package/native/cmd/ttsc-typia/compare_template_literal_union_transform_test.go +241 -0
- package/native/cmd/ttsc-typia/create_assert_error_factory_arity_test.go +309 -0
- package/native/cmd/ttsc-typia/default_library_spoof_native_identity_transform_test.go +216 -0
- package/native/cmd/ttsc-typia/json_schema_dynamic_key_determinism_transform_test.go +246 -0
- package/native/cmd/ttsc-typia/json_stringify_contextual_undefined_transform_test.go +556 -0
- package/native/cmd/ttsc-typia/lib_replacement_native_identity_transform_test.go +277 -0
- package/native/cmd/ttsc-typia/local_function_named_like_typia_operation_transform_test.go +185 -0
- package/native/cmd/ttsc-typia/native_named_intersection_union_transform_test.go +390 -0
- package/native/cmd/ttsc-typia/node_buffer_native_exports_is_transform_test.go +526 -0
- package/native/cmd/ttsc-typia/package_declaration_native_identity_is_transform_test.go +293 -0
- package/native/cmd/ttsc-typia/protobuf_diagnostic_code_transform_test.go +167 -0
- package/native/cmd/ttsc-typia/recursive_conditional_alias_name_transform_test.go +307 -0
- package/native/cmd/ttsc-typia/shadowed_typia_module_declaration_diagnostic_test.go +152 -0
- package/native/cmd/ttsc-typia/symbol_index_domain_transform_test.go +316 -0
- package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +1 -3
- package/native/cmd/ttsc-typia/transform.go +23 -0
- package/native/cmd/ttsc-typia/transform_helpers_test.go +166 -25
- package/native/cmd/ttsc-typia/user_global_native_identity_transform_test.go +484 -0
- package/native/core/factories/FormatCheatSheet.go +2 -2
- package/native/core/factories/MetadataCommentTagFactory.go +26 -11
- package/native/core/factories/ProtobufFactory.go +6 -1
- package/native/core/factories/factory_utility_coverage_test.go +896 -907
- package/native/core/factories/internal/metadata/MetadataHelper.go +190 -58
- package/native/core/factories/internal/metadata/emplace_metadata_object.go +25 -0
- package/native/core/factories/internal/metadata/iterate_metadata_function.go +1 -1
- package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +103 -23
- package/native/core/factories/internal/metadata/iterate_metadata_map.go +3 -7
- package/native/core/factories/internal/metadata/iterate_metadata_native.go +32 -14
- package/native/core/factories/internal/metadata/iterate_metadata_set.go +3 -7
- package/native/core/factories/metadata_comment_tag_factory_coverage_test.go +2 -2
- package/native/core/programmers/RandomProgrammer.go +5 -2
- package/native/core/programmers/compare/CompareEqualProgrammer.go +27 -13
- package/native/core/programmers/helpers/FunctionProgrammer.go +6 -13
- package/native/core/programmers/helpers/StringifyJoinder.go +129 -50
- package/native/core/programmers/helpers/joiner_branch_coverage_test.go +116 -120
- package/native/core/programmers/iterate/iterate_check_coverage_test.go +76 -158
- package/native/core/programmers/iterate/iterate_utility_coverage_test.go +231 -270
- package/native/core/programmers/iterate/json_schema_object.go +49 -7
- package/native/core/programmers/iterate/json_schema_pattern_property_order_test.go +44 -0
- package/native/core/programmers/iterate/openapi_v3_downgrader.go +34 -1
- package/native/core/programmers/iterate/template_runtime_pattern.go +11 -0
- package/native/core/programmers/json/JsonStringifyProgrammer.go +47 -6
- package/native/core/programmers/llm/LlmApplicationProgrammer.go +9 -1
- package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +1 -1
- package/native/core/schemas/metadata/MetadataCollection.go +47 -14
- package/native/core/schemas/metadata/MetadataDefaultLibrary.go +81 -0
- package/native/core/schemas/metadata/MetadataObjectType.go +7 -18
- package/native/go.mod +4 -4
- package/native/transform/CallExpressionTransformer.go +167 -0
- package/native/transform/features/protobuf/ProtobufMessageTransformer.go +1 -1
- package/package.json +3 -7
- package/src/executable/FileSystemIdentity.ts +33 -0
- package/src/executable/TypiaGenerateWizard.ts +18 -12
- package/src/http.ts +18 -4
- package/src/internal/_ProtobufReader.ts +40 -11
- package/src/internal/_assertGuard.ts +13 -2
- package/src/internal/_isFormatIdnHostname.ts +5 -1
- package/src/internal/_isFormatTime.ts +19 -2
- package/src/internal/_jsonStringifyArray.ts +50 -0
- package/src/internal/_jsonStringifyElement.ts +19 -0
- package/src/internal/_jsonStringifyProperty.ts +30 -0
- package/src/internal/_llmApplicationFinalize.ts +6 -1
- package/src/internal/_randomArray.ts +42 -6
- package/src/internal/_randomFormatByte.ts +36 -4
- package/src/internal/_randomFormatDate.ts +4 -20
- package/src/internal/_randomFormatDatetime.ts +34 -20
- package/src/internal/_randomFormatDuration.ts +19 -4
- package/src/internal/_randomFormatHostname.ts +2 -2
- package/src/internal/_randomFormatIdnHostname.ts +8 -9
- package/src/internal/_randomFormatIpv4.ts +43 -3
- package/src/internal/_randomFormatIpv6.ts +67 -3
- package/src/internal/_randomFormatJsonPointer.ts +23 -3
- package/src/internal/_randomFormatRegex.ts +22 -6
- package/src/internal/_randomFormatRelativeJsonPointer.ts +23 -10
- package/src/internal/_randomFormatTime.ts +50 -12
- package/src/internal/_randomPattern.ts +4 -1
- package/src/internal/_randomStringLength.ts +61 -17
- package/src/internal/private/__notationRename.ts +1 -4
- package/src/internal/private/__randomComposition.ts +74 -0
- package/src/internal/private/__randomEpoch.ts +34 -0
- package/src/json.ts +16 -4
- package/src/module.ts +56 -22
- package/src/notations.ts +16 -4
- package/src/plain.ts +12 -3
- package/src/protobuf.ts +16 -4
- package/native/adapter/visit.go +0 -173
- package/native/adapter/visit_property_chain_edges_test.go +0 -129
- package/native/core/programmers/helpers/disable_function_programmer_declare.go +0 -10
- package/native/core/programmers/iterate/check_union_array_like.go +0 -422
- package/native/core/programmers/iterate/prune_object_properties.go +0 -105
- package/native/core/programmers/iterate/stringify_dynamic_properties.go +0 -219
- package/native/core/programmers/iterate/stringify_native.go +0 -14
- package/native/core/programmers/iterate/stringify_regular_properties.go +0 -112
- package/native/core/schemas/metadata/MetadataApplication.go +0 -41
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
package iterate
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"slices"
|
|
5
|
+
"testing"
|
|
6
|
+
|
|
7
|
+
nativemetadata "github.com/samchon/typia/packages/typia/native/core/schemas/metadata"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// TestJsonSchemaPatternPropertyOrderPreservesFirstPosition verifies repeated patterns keep one ordered slot.
|
|
11
|
+
//
|
|
12
|
+
// The legacy TypeScript producer stored pairs in a plain object: assigning an
|
|
13
|
+
// existing pattern replaced its value without moving or duplicating its first
|
|
14
|
+
// insertion position. The Go order record must preserve that overwrite contract.
|
|
15
|
+
//
|
|
16
|
+
// 1. Insert two patterns, then replace the first pattern with new metadata and schema values.
|
|
17
|
+
// 2. Assert the ordered keys remain unique and the map retains the replacement pair.
|
|
18
|
+
func TestJsonSchemaPatternPropertyOrderPreservesFirstPosition(t *testing.T) {
|
|
19
|
+
first := &nativemetadata.MetadataSchema{}
|
|
20
|
+
replacement := &nativemetadata.MetadataSchema{}
|
|
21
|
+
extra := json_schema_superfluous{
|
|
22
|
+
patternProperties: map[string]json_schema_metadata_schema_pair{},
|
|
23
|
+
}
|
|
24
|
+
extra.setPatternProperty("first", json_schema_metadata_schema_pair{
|
|
25
|
+
metadata: first,
|
|
26
|
+
schema: JsonSchema{"type": "string"},
|
|
27
|
+
})
|
|
28
|
+
extra.setPatternProperty("second", json_schema_metadata_schema_pair{
|
|
29
|
+
metadata: &nativemetadata.MetadataSchema{},
|
|
30
|
+
schema: JsonSchema{"type": "boolean"},
|
|
31
|
+
})
|
|
32
|
+
extra.setPatternProperty("first", json_schema_metadata_schema_pair{
|
|
33
|
+
metadata: replacement,
|
|
34
|
+
schema: JsonSchema{"type": "number"},
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
if slices.Equal(extra.patternPropertyKeys, []string{"first", "second"}) == false {
|
|
38
|
+
t.Fatalf("pattern property order was %v", extra.patternPropertyKeys)
|
|
39
|
+
}
|
|
40
|
+
pair := extra.patternProperties["first"]
|
|
41
|
+
if pair.metadata != replacement || pair.schema["type"] != "number" {
|
|
42
|
+
t.Fatalf("replacement pair was not retained: %#v", pair)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -454,7 +454,40 @@ func openApiV3Downgrader_omit_examples(schema JsonSchema) JsonSchema {
|
|
|
454
454
|
}
|
|
455
455
|
output[key] = value
|
|
456
456
|
}
|
|
457
|
-
return output
|
|
457
|
+
return openApiV3Downgrader_exclusive_bounds(output)
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// openApiV3Downgrader_exclusive_bounds rewrites an exclusive numeric bound into
|
|
461
|
+
// the form the 3.0 dialect defines.
|
|
462
|
+
//
|
|
463
|
+
// 3.0's Schema Object descends from JSON Schema draft-04, where
|
|
464
|
+
// `exclusiveMinimum` and `exclusiveMaximum` are booleans qualifying `minimum`
|
|
465
|
+
// and `maximum`; the numeric spelling belongs to 3.1. Carrying the number
|
|
466
|
+
// through left a document that declares itself 3.0 with a 3.1 keyword, and a
|
|
467
|
+
// 3.0 reader taking the value as the boolean its dialect declares finds no
|
|
468
|
+
// `minimum` beside it and drops the bound entirely (#2300).
|
|
469
|
+
//
|
|
470
|
+
// The upgrader already performs the inverse — a boolean `exclusiveMinimum: true`
|
|
471
|
+
// becomes the numeric bound and the redundant `minimum` is dropped — so this
|
|
472
|
+
// makes the pair a round trip.
|
|
473
|
+
func openApiV3Downgrader_exclusive_bounds(schema JsonSchema) JsonSchema {
|
|
474
|
+
for _, pair := range [][2]string{
|
|
475
|
+
{"exclusiveMinimum", "minimum"},
|
|
476
|
+
{"exclusiveMaximum", "maximum"},
|
|
477
|
+
} {
|
|
478
|
+
value, ok := schema[pair[0]]
|
|
479
|
+
if ok == false {
|
|
480
|
+
continue
|
|
481
|
+
}
|
|
482
|
+
if _, boolean := value.(bool); boolean {
|
|
483
|
+
continue
|
|
484
|
+
}
|
|
485
|
+
if openApiV3Downgrader_is_nil(value) == false {
|
|
486
|
+
schema[pair[1]] = value
|
|
487
|
+
schema[pair[0]] = true
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return schema
|
|
458
491
|
}
|
|
459
492
|
|
|
460
493
|
// openApiV3Downgrader_shallow_clone copies a schema's own keys, leaving nested
|
|
@@ -25,6 +25,17 @@ type templateCapture struct {
|
|
|
25
25
|
Atomic *nativemetadata.MetadataAtomic
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
// TemplateRuntimePattern returns the structural regular-expression pattern the
|
|
29
|
+
// runtime template checker uses for one template-literal row.
|
|
30
|
+
//
|
|
31
|
+
// Consumers that only need template membership can share the checker's exact
|
|
32
|
+
// pattern without duplicating its lowering. Runtime tag conditions remain owned
|
|
33
|
+
// by Check_template because they require the checker context and capture map.
|
|
34
|
+
func TemplateRuntimePattern(row []*nativemetadata.MetadataSchema) string {
|
|
35
|
+
pattern, _ := template_runtime_pattern(row)
|
|
36
|
+
return pattern
|
|
37
|
+
}
|
|
38
|
+
|
|
28
39
|
// template_runtime_pattern builds the structural regex of a template literal for
|
|
29
40
|
// the runtime checker and, alongside it, the capture map of every constrained
|
|
30
41
|
// interpolation placeholder.
|
|
@@ -278,7 +278,34 @@ func jsonStringifyProgrammer_decode(props struct {
|
|
|
278
278
|
Value: func() *shimast.Node {
|
|
279
279
|
next := props
|
|
280
280
|
next.Metadata = metadata
|
|
281
|
-
|
|
281
|
+
resolved := jsonStringifyProgrammer_decode_to_json(next)
|
|
282
|
+
if isDate {
|
|
283
|
+
return resolved
|
|
284
|
+
}
|
|
285
|
+
// The arm's own test is `typeof input.toJSON === "function"`, but an arm
|
|
286
|
+
// test is not always emitted — a sole arm needs no choice, and a final
|
|
287
|
+
// arm is the else — while this value *calls* `toJSON`. Leaving the call
|
|
288
|
+
// to be guarded by the arm meant a value whose `toJSON` is not callable
|
|
289
|
+
// threw `input.toJSON is not a function` from inside the serializer,
|
|
290
|
+
// including under `isStringify` and `validateStringify`, whose contract
|
|
291
|
+
// is to answer rather than throw (samchon/typia#2271).
|
|
292
|
+
//
|
|
293
|
+
// The guard therefore belongs to the call. `JSON.stringify` ignores a
|
|
294
|
+
// non-callable `toJSON` and serializes the object itself, and the
|
|
295
|
+
// metadata already carries that shape, so the fallback describes the
|
|
296
|
+
// original rather than inventing an answer. `Date` keeps the plain form:
|
|
297
|
+
// its arm is `instanceof Date`, and a real Date's `toJSON` is callable.
|
|
298
|
+
original := props
|
|
299
|
+
original.Metadata = props.Metadata.Escaped.Original
|
|
300
|
+
return nativefactories.ExpressionFactory.Conditional(
|
|
301
|
+
nativeprogrammers.IsProgrammer.Decode_to_json(struct {
|
|
302
|
+
Input *shimast.Expression
|
|
303
|
+
CheckNull bool
|
|
304
|
+
}{Input: props.Input, CheckNull: false}),
|
|
305
|
+
resolved,
|
|
306
|
+
jsonStringifyProgrammer_decode(original),
|
|
307
|
+
props.Context.Emit,
|
|
308
|
+
)
|
|
282
309
|
},
|
|
283
310
|
})
|
|
284
311
|
} else if len(props.Metadata.Functions) != 0 {
|
|
@@ -697,9 +724,10 @@ func jsonStringifyProgrammer_decode_array_inline(props jsonStringifyProgrammer_d
|
|
|
697
724
|
Arrow *shimast.Node
|
|
698
725
|
}) *shimast.Node {
|
|
699
726
|
return nativehelpers.StringifyJoiner.Array(nativehelpers.StringifyJoiner_ArrayProps{
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
727
|
+
Context: props.Context,
|
|
728
|
+
Input: next.Input,
|
|
729
|
+
Arrow: next.Arrow,
|
|
730
|
+
Emit: props.Context.Emit,
|
|
703
731
|
})
|
|
704
732
|
},
|
|
705
733
|
Array: props.Array,
|
|
@@ -772,7 +800,7 @@ func jsonStringifyProgrammer_decode_tuple_inline(props jsonStringifyProgrammer_d
|
|
|
772
800
|
} else {
|
|
773
801
|
explore.Postfix = fmt.Sprintf("\"[%d]\"", index)
|
|
774
802
|
}
|
|
775
|
-
|
|
803
|
+
code := jsonStringifyProgrammer_decode(struct {
|
|
776
804
|
Context nativecontext.ITypiaContext
|
|
777
805
|
Config nativeinternal.FeatureProgrammer_IConfig
|
|
778
806
|
Functor *nativehelpers.FunctionProgrammer
|
|
@@ -788,7 +816,20 @@ func jsonStringifyProgrammer_decode_tuple_inline(props jsonStringifyProgrammer_d
|
|
|
788
816
|
Metadata: elem,
|
|
789
817
|
Explore: explore,
|
|
790
818
|
Validated: props.Validated,
|
|
791
|
-
})
|
|
819
|
+
})
|
|
820
|
+
if nativehelpers.StringifyJoiner_ResultUndefinable(elem) {
|
|
821
|
+
// A tuple slot holds its position, so an element that serializes to
|
|
822
|
+
// nothing is `null` rather than omitted; without this its text was the
|
|
823
|
+
// literal `undefined` (#2253).
|
|
824
|
+
code = f.NewCallExpression(
|
|
825
|
+
jsonStringifyProgrammer_internal(props.Context, "jsonStringifyElement"),
|
|
826
|
+
nil,
|
|
827
|
+
nil,
|
|
828
|
+
f.NewNodeList([]*shimast.Node{code}),
|
|
829
|
+
shimast.NodeFlagsNone,
|
|
830
|
+
)
|
|
831
|
+
}
|
|
832
|
+
elements = append(elements, code)
|
|
792
833
|
}
|
|
793
834
|
var rest *shimast.Node
|
|
794
835
|
if len(props.Tuple.Elements) != 0 {
|
|
@@ -240,7 +240,15 @@ func (llmApplicationProgrammerNamespace) WriteApplication(props struct {
|
|
|
240
240
|
functions = append(functions, written)
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
|
-
|
|
243
|
+
// The call site's schema configuration is resolved here and nowhere else, so
|
|
244
|
+
// it travels with the emitted application; the runtime finalizer only adds
|
|
245
|
+
// the validate hook to it. Rebuilding it at runtime reported `strict: false`
|
|
246
|
+
// for a strict build (issue #2293).
|
|
247
|
+
strict, _ := props.Config["strict"].(bool)
|
|
248
|
+
result := map[string]any{
|
|
249
|
+
"config": map[string]any{"strict": strict},
|
|
250
|
+
"functions": functions,
|
|
251
|
+
}
|
|
244
252
|
if len(metadata.Objects) != 0 {
|
|
245
253
|
if object := metadata.Objects[0].Type; object != nil {
|
|
246
254
|
if description := llmApplicationProgrammer_describe(object.Description, object.JsDocTags); description != nil && len(*description) != 0 {
|
|
@@ -35,7 +35,7 @@ func (protobufMessageProgrammerNamespace) Write(props ProtobufMessageProgrammer_
|
|
|
35
35
|
f := nativecontext.EmitFactoryOf(protobufMessageProgrammer_factory, props.Context.Emit)
|
|
36
36
|
collection := schemametadata.NewMetadataCollection()
|
|
37
37
|
nativefactories.ProtobufFactory.Metadata(nativefactories.ProtobufFactory_IProps{
|
|
38
|
-
Method: "message",
|
|
38
|
+
Method: "typia.protobuf.message",
|
|
39
39
|
Checker: props.Context.Checker,
|
|
40
40
|
Components: collection,
|
|
41
41
|
Type: props.Type,
|
|
@@ -784,15 +784,6 @@ func metadataCollection_isOpenApiNameRune(ch rune) bool {
|
|
|
784
784
|
ch == '_'
|
|
785
785
|
}
|
|
786
786
|
|
|
787
|
-
func MetadataCollection_escape(str string) string {
|
|
788
|
-
for _, pair := range metadataCollection_replacers {
|
|
789
|
-
if pair.After != "" {
|
|
790
|
-
str = strings.ReplaceAll(str, pair.After, pair.Before)
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
return str
|
|
794
|
-
}
|
|
795
|
-
|
|
796
787
|
type metadataCollection_replacer struct {
|
|
797
788
|
Before string
|
|
798
789
|
After string
|
|
@@ -819,11 +810,31 @@ var metadataCollection_replacers = []metadataCollection_replacer{
|
|
|
819
810
|
}
|
|
820
811
|
|
|
821
812
|
func metadataCollection_getFullName(checker *nativechecker.Checker, typ *nativechecker.Type) string {
|
|
813
|
+
return metadataCollection_getFullNameOf(checker, typ, nil)
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// metadataCollection_getFullNameOf carries the types whose name is still being
|
|
817
|
+
// composed on the current path. A recursive type graph reaches the same *Type
|
|
818
|
+
// again before its name is finished: `type Rec<T> = T extends Date ? string : T
|
|
819
|
+
// extends (infer U)[] ? Rec<U>[] : never` instantiated at `Date | Node[]`
|
|
820
|
+
// resolves to the union `string | Rec<Node>[]`, whose array member is a
|
|
821
|
+
// reference whose sole type argument is that very union. Walking union member ->
|
|
822
|
+
// array reference -> type argument returns to the union, so the unguarded walk
|
|
823
|
+
// never terminates and overflows the plugin's stack instead of naming the type
|
|
824
|
+
// (#2331). A type reached a second time on one path is therefore named by its
|
|
825
|
+
// own symbol with its arguments left unexpanded -- the recursion's placeholder,
|
|
826
|
+
// `Array<string | Array>` for the example above -- and a symbol-less one by the
|
|
827
|
+
// anonymous marker the collection already allocates unique names from. Expanding
|
|
828
|
+
// the checker's elided rendering there instead would name every such component
|
|
829
|
+
// after a several-hundred-character structural dump.
|
|
830
|
+
func metadataCollection_getFullNameOf(
|
|
831
|
+
checker *nativechecker.Checker,
|
|
832
|
+
typ *nativechecker.Type,
|
|
833
|
+
visiting map[*nativechecker.Type]bool,
|
|
834
|
+
) string {
|
|
822
835
|
if checker == nil || typ == nil {
|
|
823
836
|
return "__type"
|
|
824
837
|
}
|
|
825
|
-
rendered := metadataCollection_sanitizeName(checker.TypeToString(typ))
|
|
826
|
-
|
|
827
838
|
// Mirror TypeFactory.getFullName: prefer the alias symbol, then the type's
|
|
828
839
|
// own symbol. getTypeNameSymbol already returns t.alias.symbol first (the
|
|
829
840
|
// alias symbol), so a non-nil result that differs from typ.Symbol() means the
|
|
@@ -835,6 +846,13 @@ func metadataCollection_getFullName(checker *nativechecker.Checker, typ *nativec
|
|
|
835
846
|
if symbol == nil {
|
|
836
847
|
symbol = rawSymbol
|
|
837
848
|
}
|
|
849
|
+
if visiting[typ] {
|
|
850
|
+
if symbol != nil {
|
|
851
|
+
return metadataCollection_getName(symbol)
|
|
852
|
+
}
|
|
853
|
+
return "__type"
|
|
854
|
+
}
|
|
855
|
+
rendered := metadataCollection_sanitizeName(checker.TypeToString(typ))
|
|
838
856
|
if symbol == nil {
|
|
839
857
|
if typ.IsUnion() || typ.IsIntersection() {
|
|
840
858
|
joiner := " | "
|
|
@@ -843,9 +861,11 @@ func metadataCollection_getFullName(checker *nativechecker.Checker, typ *nativec
|
|
|
843
861
|
}
|
|
844
862
|
children := typ.Types()
|
|
845
863
|
names := make([]string, 0, len(children))
|
|
864
|
+
visiting = metadataCollection_markVisiting(visiting, typ)
|
|
846
865
|
for _, child := range children {
|
|
847
|
-
names = append(names,
|
|
866
|
+
names = append(names, metadataCollection_getFullNameOf(checker, child, visiting))
|
|
848
867
|
}
|
|
868
|
+
delete(visiting, typ)
|
|
849
869
|
return strings.Join(names, joiner)
|
|
850
870
|
}
|
|
851
871
|
if rendered != "" {
|
|
@@ -873,16 +893,29 @@ func metadataCollection_getFullName(checker *nativechecker.Checker, typ *nativec
|
|
|
873
893
|
}
|
|
874
894
|
return name
|
|
875
895
|
}
|
|
896
|
+
visiting = metadataCollection_markVisiting(visiting, typ)
|
|
897
|
+
defer delete(visiting, typ)
|
|
876
898
|
if name == "Promise" {
|
|
877
|
-
return
|
|
899
|
+
return metadataCollection_getFullNameOf(checker, generic[0], visiting)
|
|
878
900
|
}
|
|
879
901
|
names := make([]string, 0, len(generic))
|
|
880
902
|
for _, child := range generic {
|
|
881
|
-
names = append(names,
|
|
903
|
+
names = append(names, metadataCollection_getFullNameOf(checker, child, visiting))
|
|
882
904
|
}
|
|
883
905
|
return name + "<" + strings.Join(names, ", ") + ">"
|
|
884
906
|
}
|
|
885
907
|
|
|
908
|
+
func metadataCollection_markVisiting(
|
|
909
|
+
visiting map[*nativechecker.Type]bool,
|
|
910
|
+
typ *nativechecker.Type,
|
|
911
|
+
) map[*nativechecker.Type]bool {
|
|
912
|
+
if visiting == nil {
|
|
913
|
+
visiting = map[*nativechecker.Type]bool{}
|
|
914
|
+
}
|
|
915
|
+
visiting[typ] = true
|
|
916
|
+
return visiting
|
|
917
|
+
}
|
|
918
|
+
|
|
886
919
|
func metadataCollection_getName(symbol *nativeast.Symbol) string {
|
|
887
920
|
if symbol == nil || len(symbol.Declarations) == 0 || symbol.Declarations[0].Parent == nil {
|
|
888
921
|
return "__type"
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
package metadata
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"strings"
|
|
5
|
+
"sync"
|
|
6
|
+
|
|
7
|
+
nativeast "github.com/microsoft/typescript-go/shim/ast"
|
|
8
|
+
nativechecker "github.com/microsoft/typescript-go/shim/checker"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
// MetadataDefaultLibrary routes the compiler's own default-library
|
|
12
|
+
// classification to metadata analysis, which decides runtime-native identity
|
|
13
|
+
// from it: a global is the JavaScript built-in only when a runtime authority —
|
|
14
|
+
// a TypeScript default library, or Node's `buffer` core module — declares it
|
|
15
|
+
// (#2200).
|
|
16
|
+
//
|
|
17
|
+
// Only the program knows which files those are. `bundled:///libs/lib.es2022.d.ts`
|
|
18
|
+
// under the embedded default, an on-disk path under `noembed`, and
|
|
19
|
+
// `node_modules/@typescript/lib-es2022/index.d.ts` under `libReplacement` are
|
|
20
|
+
// all the same authority, and none of them is recognizable from the file name:
|
|
21
|
+
// the last one does not even start with `lib.`, while `lib.d.ts` is an ordinary
|
|
22
|
+
// published file name that any dependency or `typeRoots` package may use
|
|
23
|
+
// (samchon/typia#2108 recorded the same lesson for dependency reporting).
|
|
24
|
+
//
|
|
25
|
+
// The registry is keyed by checker for the same reason MetadataDependency is:
|
|
26
|
+
// analysis code deep inside the metadata iterators holds the checker but no
|
|
27
|
+
// transform context, while one transform host drives one program at a time. A
|
|
28
|
+
// sync.Map keeps unrelated programs in the same process (tests) isolated.
|
|
29
|
+
//
|
|
30
|
+
// When no classifier is registered the file name is the only evidence left, so
|
|
31
|
+
// the fallback is the historical `lib.*.d.ts` base-name test. That keeps a host
|
|
32
|
+
// that never registers on exactly the behavior this package had before the
|
|
33
|
+
// registry existed rather than silently classifying every real native as a
|
|
34
|
+
// user declaration.
|
|
35
|
+
var metadataDefaultLibrary_classifiers sync.Map
|
|
36
|
+
|
|
37
|
+
// MetadataDefaultLibrary_register records the program-level classifier for
|
|
38
|
+
// `checker`. Register it once per loaded program, before any transform runs.
|
|
39
|
+
func MetadataDefaultLibrary_register(checker *nativechecker.Checker, classifier func(*nativeast.SourceFile) bool) {
|
|
40
|
+
if checker == nil || classifier == nil {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
metadataDefaultLibrary_classifiers.Store(checker, classifier)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// MetadataDefaultLibrary_release removes the classifier registered for
|
|
47
|
+
// `checker`.
|
|
48
|
+
func MetadataDefaultLibrary_release(checker *nativechecker.Checker) {
|
|
49
|
+
if checker == nil {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
metadataDefaultLibrary_classifiers.Delete(checker)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// MetadataDefaultLibrary_is reports whether `source` is one of the program's
|
|
56
|
+
// default library files.
|
|
57
|
+
func MetadataDefaultLibrary_is(checker *nativechecker.Checker, source *nativeast.SourceFile) bool {
|
|
58
|
+
if source == nil {
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
if checker != nil {
|
|
62
|
+
if stored, ok := metadataDefaultLibrary_classifiers.Load(checker); ok {
|
|
63
|
+
if classifier, ok := stored.(func(*nativeast.SourceFile) bool); ok {
|
|
64
|
+
return classifier(source)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return MetadataDefaultLibrary_isFileNamed(source.FileName())
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// MetadataDefaultLibrary_isFileNamed is the registry's file-name fallback,
|
|
72
|
+
// exported so the one predicate that still answers without a checker keeps
|
|
73
|
+
// using the same rule.
|
|
74
|
+
func MetadataDefaultLibrary_isFileNamed(fileName string) bool {
|
|
75
|
+
slash := strings.ReplaceAll(fileName, "\\", "/")
|
|
76
|
+
base := slash
|
|
77
|
+
if index := strings.LastIndex(slash, "/"); index >= 0 {
|
|
78
|
+
base = slash[index+1:]
|
|
79
|
+
}
|
|
80
|
+
return strings.HasPrefix(base, "lib.") && strings.HasSuffix(base, ".d.ts")
|
|
81
|
+
}
|
|
@@ -13,25 +13,25 @@ type IMetadataSchema_IObjectType struct {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
type MetadataObjectType struct {
|
|
16
|
-
Name
|
|
17
|
-
DisplayName
|
|
16
|
+
Name string
|
|
17
|
+
DisplayName string
|
|
18
18
|
// Source is the absolute-or-as-declared path of the file declaring a named
|
|
19
19
|
// class, captured at analysis time so plain.classify can value-import a
|
|
20
20
|
// cross-module class it reconstructs (Object.create / new / from). nil for
|
|
21
21
|
// anonymous/literal shapes and types with no locatable declaration. Read
|
|
22
22
|
// in-process by the classify programmer; not serialized (classify is
|
|
23
23
|
// single-pass), and ignored by clone/prune.
|
|
24
|
-
Source
|
|
24
|
+
Source *string
|
|
25
25
|
// SourceDefault is true when the class is the default export of Source, so a
|
|
26
26
|
// cross-module classify value-import uses a default (not named) import.
|
|
27
|
-
SourceDefault
|
|
27
|
+
SourceDefault bool
|
|
28
28
|
// PrivateFields is true when the named class declaration carries at least one
|
|
29
29
|
// ES `#private` member (a member named with a PrivateIdentifier). Such slots
|
|
30
30
|
// are installed only by running the constructor; plain.classify's field-copy
|
|
31
31
|
// (Object.create + assign) cannot restore them, so classify rejects any such
|
|
32
32
|
// class at a field-copied position. Read in-process by the classify
|
|
33
33
|
// programmer; ignored by clone/prune, not serialized.
|
|
34
|
-
PrivateFields
|
|
34
|
+
PrivateFields bool
|
|
35
35
|
// IsClass is true when this object's declaration is a `class` (declaration or
|
|
36
36
|
// expression), so it has a runtime VALUE binding plain.classify can
|
|
37
37
|
// `Object.create(<name>.prototype)`/`new` against. False for an interface, a
|
|
@@ -39,7 +39,7 @@ type MetadataObjectType struct {
|
|
|
39
39
|
// value, so classify field-copies a plain {} instead of referencing a
|
|
40
40
|
// type-only name. Read in-process by the classify programmer; ignored by
|
|
41
41
|
// clone/prune, not serialized.
|
|
42
|
-
IsClass
|
|
42
|
+
IsClass bool
|
|
43
43
|
// ValueRef overrides the runtime VALUE-binding name plain.classify uses when
|
|
44
44
|
// the class's metadata Name is not a usable runtime constructor reference —
|
|
45
45
|
// namely a NAMED class EXPRESSION (`const X = class Beast {...}`), whose Name
|
|
@@ -56,7 +56,7 @@ type MetadataObjectType struct {
|
|
|
56
56
|
Validated bool
|
|
57
57
|
Recursive bool
|
|
58
58
|
Nullables []bool
|
|
59
|
-
Parent_objects_
|
|
59
|
+
Parent_objects_ []*MetadataObject
|
|
60
60
|
Check_properties_ []*MetadataProperty
|
|
61
61
|
Tagged_ bool
|
|
62
62
|
literal_ *bool
|
|
@@ -205,17 +205,6 @@ func (obj *MetadataObjectType) ToJSON() IMetadataSchema_IObjectType {
|
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
func MetadataObjectType_intersects(x *MetadataObjectType, y *MetadataObjectType) bool {
|
|
209
|
-
for _, prop := range x.Properties {
|
|
210
|
-
for _, oppo := range y.Properties {
|
|
211
|
-
if prop.Key.GetName() == oppo.Key.GetName() {
|
|
212
|
-
return true
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
return false
|
|
217
|
-
}
|
|
218
|
-
|
|
219
208
|
func MetadataObjectType_covers(x *MetadataObjectType, y *MetadataObjectType) bool {
|
|
220
209
|
if len(x.Properties) < len(y.Properties) {
|
|
221
210
|
return false
|
package/native/go.mod
CHANGED
|
@@ -5,10 +5,10 @@ go 1.26
|
|
|
5
5
|
// Build-time floor: the driver reference-graph SDK
|
|
6
6
|
// (driver.NewTransformGraph / driver.TransformGraph / driver.TransformOutputKey)
|
|
7
7
|
// this plugin consumes exists only in ttsc >= 0.19.2. That floor is enforced
|
|
8
|
-
// through typia's package.json
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
8
|
+
// through typia's package.json `ttsc` peerDependency, not here: ttsc builds
|
|
9
|
+
// this plugin from source on the user's machine and its buildSourcePlugin
|
|
10
|
+
// generates `replace github.com/samchon/ttsc/packages/ttsc v0.0.0 =>
|
|
11
|
+
// <installed ttsc root>`, so the require below must stay v0.0.0 or the
|
|
12
12
|
// generated replace no longer matches and the plugin build fails to resolve.
|
|
13
13
|
require (
|
|
14
14
|
github.com/microsoft/typescript-go/shim/ast v0.0.0
|
|
@@ -63,6 +63,7 @@ func (callExpressionTransformerNamespace) Transform(props CallExpressionTransfor
|
|
|
63
63
|
location, _ := filepath.Abs(sourceFile.FileName())
|
|
64
64
|
module, ok := callExpressionTransformer_targetModule(location)
|
|
65
65
|
if ok == false {
|
|
66
|
+
callExpressionTransformer_rejectShadowedTypia(props, location)
|
|
66
67
|
return props.Expression.AsNode()
|
|
67
68
|
}
|
|
68
69
|
typ := props.Context.Checker.GetTypeAtLocation(declaration)
|
|
@@ -127,6 +128,172 @@ func callExpressionTransformer_targetModule(location string) (string, bool) {
|
|
|
127
128
|
return "", false
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
// callExpressionTransformer_rejectShadowedTypia raises a diagnostic when a call
|
|
132
|
+
// the file-path identity test rejected is nevertheless a typia call the author
|
|
133
|
+
// expects to be transformed, and names the file that declared it instead.
|
|
134
|
+
//
|
|
135
|
+
// Attribution by declaration file is deliberate: accepting a callee declared
|
|
136
|
+
// anywhere else would let any package claim typia's transform, which is the
|
|
137
|
+
// boundary default_library_spoof_native_identity_transform_test.go and
|
|
138
|
+
// lib_replacement_native_identity_transform_test.go protect. That check is not
|
|
139
|
+
// relaxed here. Silence is what needs correcting. A project-local `declare
|
|
140
|
+
// module "typia"` moves the resolved signature's declaration out of typia's own
|
|
141
|
+
// files, so the call is left untransformed with no diagnostic at all and the
|
|
142
|
+
// failure surfaces only at run time as `no transform has been configured`
|
|
143
|
+
// (samchon/typia#2328).
|
|
144
|
+
//
|
|
145
|
+
// Three conditions have to hold together, so an unrelated local function that
|
|
146
|
+
// happens to share a name with a typia operation cannot trip this:
|
|
147
|
+
//
|
|
148
|
+
// 1. the callee spells an operation this transformer owns, in the namespace it
|
|
149
|
+
// actually lives in — `typia.json.assertParse`, never `typia.assertParse`;
|
|
150
|
+
// 2. the root of the callee expression resolves to an import binding; and
|
|
151
|
+
// 3. that import's module specifier is typia's own.
|
|
152
|
+
//
|
|
153
|
+
// Known gap: an alias chain is not followed, so a project that re-exports typia
|
|
154
|
+
// through its own barrel and then shadows it is still silent. The specifier of
|
|
155
|
+
// the import the call actually reads is the only evidence this collects.
|
|
156
|
+
func callExpressionTransformer_rejectShadowedTypia(props CallExpressionTransformer_TransformProps, location string) {
|
|
157
|
+
code, ok := callExpressionTransformer_calleeOperation(props.Expression.Expression)
|
|
158
|
+
if ok == false {
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
root := callExpressionTransformer_calleeRoot(props.Expression.Expression)
|
|
162
|
+
if root == nil || root.Kind != shimast.KindIdentifier {
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
symbol := props.Context.Checker.GetSymbolAtLocation(root)
|
|
166
|
+
if symbol == nil || symbol.Flags&shimast.SymbolFlagsAlias == 0 {
|
|
167
|
+
return
|
|
168
|
+
}
|
|
169
|
+
for _, declaration := range symbol.Declarations {
|
|
170
|
+
if callExpressionTransformer_importsTypia(declaration) == false {
|
|
171
|
+
continue
|
|
172
|
+
}
|
|
173
|
+
// State only what was observed. The declaration file is the fact; a
|
|
174
|
+
// `declare module "typia"` is the usual cause but not the only way to move
|
|
175
|
+
// a declaration, and naming it as the cause would misdirect anyone whose
|
|
176
|
+
// build got here another way.
|
|
177
|
+
panic(nativecontext.NewTransformerError(nativecontext.TransformerError_IProps{
|
|
178
|
+
Code: code,
|
|
179
|
+
Message: "this call was declared in " +
|
|
180
|
+
filepath.ToSlash(location) +
|
|
181
|
+
", not in typia's own module, so no transform was applied. A project-local `declare module \"typia\"` is the usual cause; remove it, or give the redeclaration another module name.",
|
|
182
|
+
}))
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// callExpressionTransformer_calleeOperation answers whether a callee expression
|
|
187
|
+
// spells one of this transformer's operations, and returns the diagnostic code
|
|
188
|
+
// for it — the written spelling, qualified as `typia.json.assertParse`.
|
|
189
|
+
//
|
|
190
|
+
// The namespace is part of the spelling. `typia.json.assertParse` names the
|
|
191
|
+
// `json` table, while `typia.createAssert` and a bare named import name the root
|
|
192
|
+
// `module` table; a root-level `typia.assertParse` matches nothing, because that
|
|
193
|
+
// operation does not live there. Matching a flat union of every table's names
|
|
194
|
+
// instead would report a module augmentation that adds an unrelated `parse` or
|
|
195
|
+
// `schema` to typia, which is a build that works today.
|
|
196
|
+
//
|
|
197
|
+
// Known gap: taking the namespace from the spelling means a renamed binding
|
|
198
|
+
// (`import { json as j } from "typia"; j.assertParse(...)`) is not recognized.
|
|
199
|
+
func callExpressionTransformer_calleeOperation(callee *shimast.Node) (string, bool) {
|
|
200
|
+
method := ""
|
|
201
|
+
first := true
|
|
202
|
+
// Segments to the left of the method, nearest first: `typia.json.assertParse`
|
|
203
|
+
// collects ["json", "typia"].
|
|
204
|
+
parts := []string{}
|
|
205
|
+
for current := callee; current != nil; {
|
|
206
|
+
if len(parts) > 2 {
|
|
207
|
+
return "", false
|
|
208
|
+
}
|
|
209
|
+
segment := ""
|
|
210
|
+
switch current.Kind {
|
|
211
|
+
case shimast.KindPropertyAccessExpression:
|
|
212
|
+
access := current.AsPropertyAccessExpression()
|
|
213
|
+
name := access.Name()
|
|
214
|
+
if name == nil || name.Kind != shimast.KindIdentifier {
|
|
215
|
+
return "", false
|
|
216
|
+
}
|
|
217
|
+
segment = name.Text()
|
|
218
|
+
current = access.Expression
|
|
219
|
+
case shimast.KindIdentifier:
|
|
220
|
+
segment = current.Text()
|
|
221
|
+
current = nil
|
|
222
|
+
default:
|
|
223
|
+
return "", false
|
|
224
|
+
}
|
|
225
|
+
if first {
|
|
226
|
+
method = segment
|
|
227
|
+
first = false
|
|
228
|
+
} else {
|
|
229
|
+
parts = append(parts, segment)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if method == "" || len(parts) > 2 {
|
|
233
|
+
return "", false
|
|
234
|
+
}
|
|
235
|
+
functors := callExpressionTransformer_FUNCTORS()
|
|
236
|
+
// `typia.json.assertParse` and `json.assertParse` both name the `json` table
|
|
237
|
+
// through the segment directly left of the method.
|
|
238
|
+
if len(parts) != 0 {
|
|
239
|
+
if _, found := functors[parts[0]][method]; found {
|
|
240
|
+
return "typia." + parts[0] + "." + method, true
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// `typia.createAssert` and a bare `createAssert` name the root table. The
|
|
244
|
+
// qualifier, when present, is the imported binding rather than a namespace.
|
|
245
|
+
if len(parts) <= 1 {
|
|
246
|
+
if _, found := functors["module"][method]; found {
|
|
247
|
+
return "typia." + method, true
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return "", false
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// callExpressionTransformer_calleeRoot walks a property-access chain down to the
|
|
254
|
+
// expression it starts from, which is the binding that has to come from typia.
|
|
255
|
+
func callExpressionTransformer_calleeRoot(callee *shimast.Node) *shimast.Node {
|
|
256
|
+
current := callee
|
|
257
|
+
for current != nil && current.Kind == shimast.KindPropertyAccessExpression {
|
|
258
|
+
current = current.AsPropertyAccessExpression().Expression
|
|
259
|
+
}
|
|
260
|
+
return current
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// callExpressionTransformer_importsTypia answers whether an alias declaration
|
|
264
|
+
// belongs to an import whose module specifier is typia's own. Both `import ...
|
|
265
|
+
// from "typia"` and `import typia = require("typia")` are matched; the walk
|
|
266
|
+
// stops at the source file so a local declaration can never reach an unrelated
|
|
267
|
+
// import above it.
|
|
268
|
+
func callExpressionTransformer_importsTypia(declaration *shimast.Node) bool {
|
|
269
|
+
for node := declaration; node != nil; node = node.Parent {
|
|
270
|
+
switch node.Kind {
|
|
271
|
+
case shimast.KindImportDeclaration:
|
|
272
|
+
return callExpressionTransformer_isTypiaSpecifier(node.ModuleSpecifier())
|
|
273
|
+
case shimast.KindImportEqualsDeclaration:
|
|
274
|
+
reference := node.AsImportEqualsDeclaration().ModuleReference
|
|
275
|
+
if reference == nil || reference.Kind != shimast.KindExternalModuleReference {
|
|
276
|
+
return false
|
|
277
|
+
}
|
|
278
|
+
return callExpressionTransformer_isTypiaSpecifier(reference.AsExternalModuleReference().Expression)
|
|
279
|
+
case shimast.KindSourceFile:
|
|
280
|
+
return false
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return false
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// callExpressionTransformer_isTypiaSpecifier accepts typia's own package name
|
|
287
|
+
// and its subpaths, and nothing that merely begins with those letters: a
|
|
288
|
+
// `typia-codegen` package is a different package.
|
|
289
|
+
func callExpressionTransformer_isTypiaSpecifier(specifier *shimast.Node) bool {
|
|
290
|
+
if specifier == nil || specifier.Kind != shimast.KindStringLiteral {
|
|
291
|
+
return false
|
|
292
|
+
}
|
|
293
|
+
text := specifier.AsStringLiteral().Text
|
|
294
|
+
return text == "typia" || strings.HasPrefix(text, "typia/")
|
|
295
|
+
}
|
|
296
|
+
|
|
130
297
|
func callExpressionTransformer_sourceFile(node *shimast.Node) *shimast.SourceFile {
|
|
131
298
|
for current := node; current != nil; current = current.Parent {
|
|
132
299
|
if current.Kind == shimast.KindSourceFile {
|