@nestia/core 11.2.1 → 12.0.0-dev.20260520.1
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/MIGRATION.md +169 -0
- package/lib/adaptors/WebSocketAdaptor.js +7 -3
- package/lib/adaptors/WebSocketAdaptor.js.map +1 -1
- package/lib/decorators/DynamicModule.js.map +1 -1
- package/lib/decorators/EncryptedBody.js.map +1 -1
- package/lib/decorators/EncryptedController.js.map +1 -1
- package/lib/decorators/EncryptedModule.js.map +1 -1
- package/lib/decorators/EncryptedRoute.js.map +1 -1
- package/lib/decorators/HumanRoute.js.map +1 -1
- package/lib/decorators/NoTransformConfigurationError.js +5 -2
- package/lib/decorators/NoTransformConfigurationError.js.map +1 -1
- package/lib/decorators/PlainBody.js.map +1 -1
- package/lib/decorators/SwaggerCustomizer.js.map +1 -1
- package/lib/decorators/SwaggerExample.js.map +1 -1
- package/lib/decorators/TypedBody.js.map +1 -1
- package/lib/decorators/TypedException.js.map +1 -1
- package/lib/decorators/TypedFormData.js.map +1 -1
- package/lib/decorators/TypedHeaders.js.map +1 -1
- package/lib/decorators/TypedParam.js +5 -2
- package/lib/decorators/TypedParam.js.map +1 -1
- package/lib/decorators/TypedQuery.js.map +1 -1
- package/lib/decorators/TypedRoute.js.map +1 -1
- package/lib/decorators/WebSocketRoute.js.map +1 -1
- package/lib/decorators/doNotThrowTransformError.js.map +1 -1
- package/lib/decorators/internal/get_path_and_querify.js +5 -2
- package/lib/decorators/internal/get_path_and_querify.js.map +1 -1
- package/lib/decorators/internal/get_path_and_stringify.js +5 -2
- package/lib/decorators/internal/get_path_and_stringify.js.map +1 -1
- package/lib/decorators/internal/get_text_body.js.map +1 -1
- package/lib/decorators/internal/headers_to_object.js.map +1 -1
- package/lib/decorators/internal/is_request_body_undefined.js.map +1 -1
- package/lib/decorators/internal/load_controller.js +48 -16
- package/lib/decorators/internal/load_controller.js.map +1 -1
- package/lib/decorators/internal/route_error.js +3 -3
- package/lib/decorators/internal/route_error.js.map +1 -1
- package/lib/decorators/internal/validate_request_body.js +5 -2
- package/lib/decorators/internal/validate_request_body.js.map +1 -1
- package/lib/decorators/internal/validate_request_form_data.js +5 -2
- package/lib/decorators/internal/validate_request_form_data.js.map +1 -1
- package/lib/decorators/internal/validate_request_headers.js +5 -2
- package/lib/decorators/internal/validate_request_headers.js.map +1 -1
- package/lib/decorators/internal/validate_request_query.js +30 -4
- package/lib/decorators/internal/validate_request_query.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/transform.d.ts +2 -5
- package/lib/transform.js +48 -28
- package/lib/transform.js.map +1 -1
- package/lib/utils/ArrayUtil.js.map +1 -1
- package/lib/utils/ExceptionManager.js.map +1 -1
- package/lib/utils/Singleton.js.map +1 -1
- package/lib/utils/SourceFinder.js.map +1 -1
- package/lib/utils/VersioningStrategy.js.map +1 -1
- package/native/cmd/ttsc-nestia/build.go +434 -0
- package/native/cmd/ttsc-nestia/cleanup.go +408 -0
- package/native/cmd/ttsc-nestia/core_querify.go +227 -0
- package/native/cmd/ttsc-nestia/core_transform.go +1713 -0
- package/native/cmd/ttsc-nestia/core_websocket.go +115 -0
- package/native/cmd/ttsc-nestia/main.go +72 -0
- package/native/cmd/ttsc-nestia/path_rewrite.go +285 -0
- package/native/cmd/ttsc-nestia/printer.go +244 -0
- package/native/cmd/ttsc-nestia/rewrite.go +662 -0
- package/native/cmd/ttsc-nestia/sdk_metadata_json.go +327 -0
- package/native/cmd/ttsc-nestia/sdk_transform.go +1541 -0
- package/native/cmd/ttsc-nestia/transform.go +387 -0
- package/native/cmd/ttsc-nestia/typia_fast.go +326 -0
- package/native/cmd/ttsc-nestia/typia_replacement.go +24 -0
- package/native/go.mod +32 -0
- package/native/go.sum +54 -0
- package/native/plugin/plan.go +102 -0
- package/native/transform.cjs +21 -0
- package/package.json +27 -22
- package/src/decorators/NoTransformConfigurationError.ts +5 -2
- package/src/decorators/internal/load_controller.ts +50 -19
- package/src/decorators/internal/validate_request_query.ts +21 -2
- package/src/transform.ts +82 -35
- package/lib/decorators/internal/NoTransformConfigureError.d.ts +0 -1
- package/lib/decorators/internal/NoTransformConfigureError.js +0 -7
- package/lib/decorators/internal/NoTransformConfigureError.js.map +0 -1
- package/lib/options/INestiaTransformOptions.d.ts +0 -13
- package/lib/options/INestiaTransformOptions.js +0 -3
- package/lib/options/INestiaTransformOptions.js.map +0 -1
- package/lib/options/INestiaTransformProject.d.ts +0 -5
- package/lib/options/INestiaTransformProject.js +0 -3
- package/lib/options/INestiaTransformProject.js.map +0 -1
- package/lib/programmers/PlainBodyProgrammer.d.ts +0 -9
- package/lib/programmers/PlainBodyProgrammer.js +0 -58
- package/lib/programmers/PlainBodyProgrammer.js.map +0 -1
- package/lib/programmers/TypedBodyProgrammer.d.ts +0 -9
- package/lib/programmers/TypedBodyProgrammer.js +0 -94
- package/lib/programmers/TypedBodyProgrammer.js.map +0 -1
- package/lib/programmers/TypedFormDataBodyProgrammer.d.ts +0 -9
- package/lib/programmers/TypedFormDataBodyProgrammer.js +0 -65
- package/lib/programmers/TypedFormDataBodyProgrammer.js.map +0 -1
- package/lib/programmers/TypedHeadersProgrammer.d.ts +0 -9
- package/lib/programmers/TypedHeadersProgrammer.js +0 -38
- package/lib/programmers/TypedHeadersProgrammer.js.map +0 -1
- package/lib/programmers/TypedParamProgrammer.d.ts +0 -10
- package/lib/programmers/TypedParamProgrammer.js +0 -32
- package/lib/programmers/TypedParamProgrammer.js.map +0 -1
- package/lib/programmers/TypedQueryBodyProgrammer.d.ts +0 -9
- package/lib/programmers/TypedQueryBodyProgrammer.js +0 -74
- package/lib/programmers/TypedQueryBodyProgrammer.js.map +0 -1
- package/lib/programmers/TypedQueryProgrammer.d.ts +0 -9
- package/lib/programmers/TypedQueryProgrammer.js +0 -75
- package/lib/programmers/TypedQueryProgrammer.js.map +0 -1
- package/lib/programmers/TypedQueryRouteProgrammer.d.ts +0 -9
- package/lib/programmers/TypedQueryRouteProgrammer.js +0 -75
- package/lib/programmers/TypedQueryRouteProgrammer.js.map +0 -1
- package/lib/programmers/TypedRouteProgrammer.d.ts +0 -9
- package/lib/programmers/TypedRouteProgrammer.js +0 -79
- package/lib/programmers/TypedRouteProgrammer.js.map +0 -1
- package/lib/programmers/http/HttpAssertQuerifyProgrammer.d.ts +0 -9
- package/lib/programmers/http/HttpAssertQuerifyProgrammer.js +0 -39
- package/lib/programmers/http/HttpAssertQuerifyProgrammer.js.map +0 -1
- package/lib/programmers/http/HttpIsQuerifyProgrammer.d.ts +0 -9
- package/lib/programmers/http/HttpIsQuerifyProgrammer.js +0 -36
- package/lib/programmers/http/HttpIsQuerifyProgrammer.js.map +0 -1
- package/lib/programmers/http/HttpQuerifyProgrammer.d.ts +0 -9
- package/lib/programmers/http/HttpQuerifyProgrammer.js +0 -50
- package/lib/programmers/http/HttpQuerifyProgrammer.js.map +0 -1
- package/lib/programmers/http/HttpValidateQuerifyProgrammer.d.ts +0 -9
- package/lib/programmers/http/HttpValidateQuerifyProgrammer.js +0 -40
- package/lib/programmers/http/HttpValidateQuerifyProgrammer.js.map +0 -1
- package/lib/programmers/internal/CoreMetadataUtil.d.ts +0 -5
- package/lib/programmers/internal/CoreMetadataUtil.js +0 -19
- package/lib/programmers/internal/CoreMetadataUtil.js.map +0 -1
- package/lib/transformers/FileTransformer.d.ts +0 -5
- package/lib/transformers/FileTransformer.js +0 -80
- package/lib/transformers/FileTransformer.js.map +0 -1
- package/lib/transformers/MethodTransformer.d.ts +0 -8
- package/lib/transformers/MethodTransformer.js +0 -58
- package/lib/transformers/MethodTransformer.js.map +0 -1
- package/lib/transformers/NodeTransformer.d.ts +0 -8
- package/lib/transformers/NodeTransformer.js +0 -24
- package/lib/transformers/NodeTransformer.js.map +0 -1
- package/lib/transformers/ParameterDecoratorTransformer.d.ts +0 -9
- package/lib/transformers/ParameterDecoratorTransformer.js +0 -104
- package/lib/transformers/ParameterDecoratorTransformer.js.map +0 -1
- package/lib/transformers/ParameterTransformer.d.ts +0 -8
- package/lib/transformers/ParameterTransformer.js +0 -37
- package/lib/transformers/ParameterTransformer.js.map +0 -1
- package/lib/transformers/TypedRouteTransformer.d.ts +0 -9
- package/lib/transformers/TypedRouteTransformer.js +0 -68
- package/lib/transformers/TypedRouteTransformer.js.map +0 -1
- package/lib/transformers/WebSocketRouteTransformer.d.ts +0 -9
- package/lib/transformers/WebSocketRouteTransformer.js +0 -72
- package/lib/transformers/WebSocketRouteTransformer.js.map +0 -1
- package/src/decorators/internal/NoTransformConfigureError.ts +0 -2
- package/src/options/INestiaTransformOptions.ts +0 -34
- package/src/options/INestiaTransformProject.ts +0 -10
- package/src/programmers/PlainBodyProgrammer.ts +0 -72
- package/src/programmers/TypedBodyProgrammer.ts +0 -148
- package/src/programmers/TypedFormDataBodyProgrammer.ts +0 -118
- package/src/programmers/TypedHeadersProgrammer.ts +0 -65
- package/src/programmers/TypedParamProgrammer.ts +0 -33
- package/src/programmers/TypedQueryBodyProgrammer.ts +0 -113
- package/src/programmers/TypedQueryProgrammer.ts +0 -115
- package/src/programmers/TypedQueryRouteProgrammer.ts +0 -107
- package/src/programmers/TypedRouteProgrammer.ts +0 -103
- package/src/programmers/http/HttpAssertQuerifyProgrammer.ts +0 -74
- package/src/programmers/http/HttpIsQuerifyProgrammer.ts +0 -77
- package/src/programmers/http/HttpQuerifyProgrammer.ts +0 -110
- package/src/programmers/http/HttpValidateQuerifyProgrammer.ts +0 -78
- package/src/programmers/internal/CoreMetadataUtil.ts +0 -21
- package/src/transformers/FileTransformer.ts +0 -109
- package/src/transformers/MethodTransformer.ts +0 -103
- package/src/transformers/NodeTransformer.ts +0 -23
- package/src/transformers/ParameterDecoratorTransformer.ts +0 -143
- package/src/transformers/ParameterTransformer.ts +0 -57
- package/src/transformers/TypedRouteTransformer.ts +0 -85
- package/src/transformers/WebSocketRouteTransformer.ts +0 -120
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"strings"
|
|
6
|
+
|
|
7
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
8
|
+
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
9
|
+
"github.com/samchon/ttsc/packages/ttsc/driver"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
func validateNestiaCoreWebSocketRoute(
|
|
13
|
+
prog *driver.Program,
|
|
14
|
+
context nestiaCoreFileContext,
|
|
15
|
+
method *shimast.Node,
|
|
16
|
+
call *shimast.CallExpression,
|
|
17
|
+
segments []string,
|
|
18
|
+
) []typiaTransformDiagnostic {
|
|
19
|
+
if call == nil || len(segments) == 0 || segments[len(segments)-1] != "WebSocketRoute" {
|
|
20
|
+
_ = call
|
|
21
|
+
return nil
|
|
22
|
+
}
|
|
23
|
+
diagnostics := []typiaTransformDiagnostic{}
|
|
24
|
+
accepted := false
|
|
25
|
+
methodDecl := method.AsMethodDeclaration()
|
|
26
|
+
if methodDecl == nil || methodDecl.Parameters == nil {
|
|
27
|
+
return []typiaTransformDiagnostic{nestiaCoreWebSocketDiagnostic(context.file, method, "WebSocketRoute", fmt.Sprintf(
|
|
28
|
+
"method %q must have at least one parameter decorated by @WebSocketRoute.Acceptor().",
|
|
29
|
+
nestiaSDKMethodName(method),
|
|
30
|
+
))}
|
|
31
|
+
}
|
|
32
|
+
for _, param := range methodDecl.Parameters.Nodes {
|
|
33
|
+
category := nestiaCoreWebSocketParameterCategory(prog, param)
|
|
34
|
+
name := nestiaSDKParameterName(param)
|
|
35
|
+
if category == "" {
|
|
36
|
+
diagnostics = append(diagnostics, nestiaCoreWebSocketDiagnostic(context.file, param, "WebSocketRoute", fmt.Sprintf(
|
|
37
|
+
"parameter %q is not decorated with nested function of WebSocketRoute module.",
|
|
38
|
+
name,
|
|
39
|
+
)))
|
|
40
|
+
continue
|
|
41
|
+
}
|
|
42
|
+
switch category {
|
|
43
|
+
case "Acceptor":
|
|
44
|
+
accepted = true
|
|
45
|
+
if strings.HasPrefix(nestiaCoreWebSocketParameterTypeName(param), "WebSocketAcceptor") == false {
|
|
46
|
+
diagnostics = append(diagnostics, nestiaCoreWebSocketDiagnostic(context.file, param, "WebSocketRoute", fmt.Sprintf(
|
|
47
|
+
"parameter %q must have WebSocketAcceptor<Header, Provider, Listener> type.",
|
|
48
|
+
name,
|
|
49
|
+
)))
|
|
50
|
+
}
|
|
51
|
+
case "Driver":
|
|
52
|
+
if strings.HasPrefix(nestiaCoreWebSocketParameterTypeName(param), "Driver") == false {
|
|
53
|
+
diagnostics = append(diagnostics, nestiaCoreWebSocketDiagnostic(context.file, param, "WebSocketRoute", fmt.Sprintf(
|
|
54
|
+
"parameter %q must have Driver<Listener> type.",
|
|
55
|
+
name,
|
|
56
|
+
)))
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if accepted == false {
|
|
61
|
+
diagnostics = append(diagnostics, nestiaCoreWebSocketDiagnostic(context.file, method, "WebSocketRoute", fmt.Sprintf(
|
|
62
|
+
"method %q must have at least one parameter decorated by @WebSocketRoute.Acceptor().",
|
|
63
|
+
nestiaSDKMethodName(method),
|
|
64
|
+
)))
|
|
65
|
+
}
|
|
66
|
+
return diagnostics
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
func nestiaCoreWebSocketParameterCategory(prog *driver.Program, param *shimast.Node) string {
|
|
70
|
+
if param == nil || len(param.Decorators()) != 1 {
|
|
71
|
+
return ""
|
|
72
|
+
}
|
|
73
|
+
call, segments, ok := nestiaCoreDecoratorCall(prog, param.Decorators()[0])
|
|
74
|
+
if ok == false || len(segments) < 2 || segments[len(segments)-2] != "WebSocketRoute" {
|
|
75
|
+
_ = call
|
|
76
|
+
return ""
|
|
77
|
+
}
|
|
78
|
+
return segments[len(segments)-1]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
func nestiaCoreWebSocketParameterTypeName(param *shimast.Node) string {
|
|
82
|
+
if param == nil || param.AsParameterDeclaration() == nil || param.AsParameterDeclaration().Type == nil {
|
|
83
|
+
return ""
|
|
84
|
+
}
|
|
85
|
+
text := nestiaSDKTypeNodeText(param.AsParameterDeclaration().Type)
|
|
86
|
+
text = strings.TrimSpace(text)
|
|
87
|
+
if index := strings.Index(text, "<"); index >= 0 {
|
|
88
|
+
text = text[:index]
|
|
89
|
+
}
|
|
90
|
+
if index := strings.LastIndex(text, "."); index >= 0 {
|
|
91
|
+
text = text[index+1:]
|
|
92
|
+
}
|
|
93
|
+
return text
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
func nestiaCoreWebSocketDiagnostic(file *shimast.SourceFile, node *shimast.Node, kind string, message string) typiaTransformDiagnostic {
|
|
97
|
+
filePath := ""
|
|
98
|
+
line, column := 0, 0
|
|
99
|
+
if file != nil {
|
|
100
|
+
filePath = file.FileName()
|
|
101
|
+
if node != nil {
|
|
102
|
+
if pos := node.Pos(); pos >= 0 {
|
|
103
|
+
l, c := shimscanner.GetECMALineAndByteOffsetOfPosition(file, pos)
|
|
104
|
+
line, column = l+1, c+1
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return typiaTransformDiagnostic{
|
|
109
|
+
File: filePath,
|
|
110
|
+
Line: line,
|
|
111
|
+
Column: column,
|
|
112
|
+
Code: "nestia.core." + kind,
|
|
113
|
+
Message: message,
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"io"
|
|
6
|
+
"os"
|
|
7
|
+
"runtime/debug"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
var (
|
|
11
|
+
stdout io.Writer = os.Stdout
|
|
12
|
+
stderr io.Writer = os.Stderr
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
func main() {
|
|
16
|
+
os.Exit(runSafe(os.Args[1:]))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// runSafe wraps run() in a panic recovery envelope so that any unexpected
|
|
20
|
+
// panic surfaces as a one-line transform-diagnostic on stderr instead of
|
|
21
|
+
// a multi-line raw Go stack trace. The diagnostic uses the same `<file> -
|
|
22
|
+
// error TS(code): message` shape as every other nestia / typia diagnostic;
|
|
23
|
+
// ttsc reads it via `error.stderr` (`RuntimeCompiler.compile` at
|
|
24
|
+
// `ConfigAnalyzer.ts:170-174`) rather than its structured-diagnostic regex,
|
|
25
|
+
// which is a pre-existing protocol shared by all `nestia.*` codes. The
|
|
26
|
+
// full stack is preserved behind NESTIA_NATIVE_DEBUG_STACK for triage.
|
|
27
|
+
func runSafe(args []string) (code int) {
|
|
28
|
+
defer func() {
|
|
29
|
+
if exp := recover(); exp != nil {
|
|
30
|
+
diag := typiaTransformDiagnostic{
|
|
31
|
+
Code: "nestia.internal.panic",
|
|
32
|
+
Message: fmt.Sprintf("ttsc-nestia panicked: %v", exp),
|
|
33
|
+
}
|
|
34
|
+
writeTypiaTransformDiagnostics(stderr, []typiaTransformDiagnostic{diag}, "")
|
|
35
|
+
if os.Getenv("NESTIA_NATIVE_DEBUG_STACK") != "" {
|
|
36
|
+
fmt.Fprintln(stderr, string(debug.Stack()))
|
|
37
|
+
}
|
|
38
|
+
code = 3
|
|
39
|
+
}
|
|
40
|
+
}()
|
|
41
|
+
return run(args)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func run(args []string) int {
|
|
45
|
+
if len(args) == 0 {
|
|
46
|
+
return runHelp(nil)
|
|
47
|
+
}
|
|
48
|
+
command := args[0]
|
|
49
|
+
rest := args[1:]
|
|
50
|
+
switch command {
|
|
51
|
+
case "build":
|
|
52
|
+
return runBuild(rest)
|
|
53
|
+
case "check":
|
|
54
|
+
return runCheck(rest)
|
|
55
|
+
case "transform":
|
|
56
|
+
return runTransform(rest)
|
|
57
|
+
case "version":
|
|
58
|
+
fmt.Fprintln(stdout, "ttsc-nestia 0.1.0")
|
|
59
|
+
return 0
|
|
60
|
+
case "help", "-h", "--help":
|
|
61
|
+
return runHelp(rest)
|
|
62
|
+
default:
|
|
63
|
+
fmt.Fprintf(stderr, "ttsc-nestia: unknown command %q\n", command)
|
|
64
|
+
return 2
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
func runHelp(args []string) int {
|
|
69
|
+
_ = args
|
|
70
|
+
fmt.Fprintln(stdout, "usage: ttsc-nestia <build|check|transform|version>")
|
|
71
|
+
return 0
|
|
72
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"path/filepath"
|
|
5
|
+
"sort"
|
|
6
|
+
"strings"
|
|
7
|
+
|
|
8
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
9
|
+
shimcore "github.com/microsoft/typescript-go/shim/core"
|
|
10
|
+
"github.com/samchon/ttsc/packages/ttsc/driver"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
type pathsRewriter struct {
|
|
14
|
+
basePath string
|
|
15
|
+
outDir string
|
|
16
|
+
patterns []pathsPattern
|
|
17
|
+
rootDir string
|
|
18
|
+
sourceFiles map[string]string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type pathsPattern struct {
|
|
22
|
+
pattern string
|
|
23
|
+
targets []string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
func newPathsRewriter(prog *driver.Program) *pathsRewriter {
|
|
27
|
+
out := &pathsRewriter{sourceFiles: map[string]string{}}
|
|
28
|
+
if prog == nil || prog.ParsedConfig == nil || prog.ParsedConfig.ParsedConfig == nil || prog.ParsedConfig.ParsedConfig.CompilerOptions == nil {
|
|
29
|
+
return out
|
|
30
|
+
}
|
|
31
|
+
options := prog.ParsedConfig.ParsedConfig.CompilerOptions
|
|
32
|
+
out.basePath = filepath.Clean(options.GetPathsBasePath(prog.Host.GetCurrentDirectory()))
|
|
33
|
+
out.outDir = optionalPath(options.OutDir, prog.Host.GetCurrentDirectory())
|
|
34
|
+
out.rootDir = optionalPath(options.RootDir, prog.Host.GetCurrentDirectory())
|
|
35
|
+
files := prog.SourceFiles()
|
|
36
|
+
if out.rootDir == "" {
|
|
37
|
+
out.rootDir = commonSourceDir(files)
|
|
38
|
+
}
|
|
39
|
+
for _, file := range files {
|
|
40
|
+
name := normalizePath(file.FileName())
|
|
41
|
+
out.sourceFiles[name] = name
|
|
42
|
+
out.sourceFiles[stripKnownSourceExtension(name)] = name
|
|
43
|
+
}
|
|
44
|
+
if options.Paths != nil {
|
|
45
|
+
for pattern, targets := range options.Paths.Entries() {
|
|
46
|
+
out.patterns = append(out.patterns, pathsPattern{
|
|
47
|
+
pattern: pattern,
|
|
48
|
+
targets: append([]string(nil), targets...),
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
sort.SliceStable(out.patterns, func(i, j int) bool {
|
|
53
|
+
return patternRank(out.patterns[i].pattern) > patternRank(out.patterns[j].pattern)
|
|
54
|
+
})
|
|
55
|
+
return out
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
func (r *pathsRewriter) applyAll(files []*shimast.SourceFile) {
|
|
59
|
+
if r == nil || len(r.patterns) == 0 {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
for _, file := range files {
|
|
63
|
+
r.apply(file)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
func (r *pathsRewriter) apply(file *shimast.SourceFile) {
|
|
68
|
+
if r == nil || file == nil || len(r.patterns) == 0 {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
visitModuleSpecifiers(file.AsNode(), func(lit *shimast.Node) {
|
|
72
|
+
if lit == nil || lit.Kind != shimast.KindStringLiteral {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
spec := lit.Text()
|
|
76
|
+
rewritten, ok := r.rewrite(file.FileName(), spec)
|
|
77
|
+
if ok && rewritten != spec {
|
|
78
|
+
lit.AsStringLiteral().Text = rewritten
|
|
79
|
+
lit.Flags |= shimast.NodeFlagsSynthesized
|
|
80
|
+
lit.Loc = shimcore.UndefinedTextRange()
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func visitModuleSpecifiers(node *shimast.Node, visit func(*shimast.Node)) {
|
|
86
|
+
if node == nil {
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
switch node.Kind {
|
|
90
|
+
case shimast.KindImportDeclaration:
|
|
91
|
+
visit(node.AsImportDeclaration().ModuleSpecifier)
|
|
92
|
+
case shimast.KindExportDeclaration:
|
|
93
|
+
visit(node.AsExportDeclaration().ModuleSpecifier)
|
|
94
|
+
case shimast.KindImportEqualsDeclaration:
|
|
95
|
+
ref := node.AsImportEqualsDeclaration().ModuleReference
|
|
96
|
+
if ref != nil && ref.Kind == shimast.KindExternalModuleReference {
|
|
97
|
+
visit(ref.AsExternalModuleReference().Expression)
|
|
98
|
+
}
|
|
99
|
+
case shimast.KindImportType:
|
|
100
|
+
arg := node.AsImportTypeNode().Argument
|
|
101
|
+
if arg != nil && arg.Kind == shimast.KindLiteralType {
|
|
102
|
+
visit(arg.AsLiteralTypeNode().Literal)
|
|
103
|
+
}
|
|
104
|
+
case shimast.KindModuleDeclaration:
|
|
105
|
+
decl := node.AsModuleDeclaration()
|
|
106
|
+
if decl != nil {
|
|
107
|
+
visit(decl.Name())
|
|
108
|
+
}
|
|
109
|
+
case shimast.KindCallExpression:
|
|
110
|
+
call := node.AsCallExpression()
|
|
111
|
+
if isModuleSpecifierCall(call) && call.Arguments != nil && len(call.Arguments.Nodes) > 0 {
|
|
112
|
+
visit(call.Arguments.Nodes[0])
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
node.ForEachChild(func(child *shimast.Node) bool {
|
|
116
|
+
visitModuleSpecifiers(child, visit)
|
|
117
|
+
return false
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
func isModuleSpecifierCall(call *shimast.CallExpression) bool {
|
|
122
|
+
if call == nil || call.Expression == nil {
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
switch call.Expression.Kind {
|
|
126
|
+
case shimast.KindImportKeyword:
|
|
127
|
+
return true
|
|
128
|
+
case shimast.KindIdentifier:
|
|
129
|
+
return call.Expression.Text() == "require"
|
|
130
|
+
default:
|
|
131
|
+
return false
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func (r *pathsRewriter) rewrite(fromSource string, specifier string) (string, bool) {
|
|
136
|
+
if specifier == "" || strings.HasPrefix(specifier, ".") || strings.HasPrefix(specifier, "/") {
|
|
137
|
+
return specifier, false
|
|
138
|
+
}
|
|
139
|
+
targetSource, ok := r.resolveSource(specifier)
|
|
140
|
+
if !ok {
|
|
141
|
+
return specifier, false
|
|
142
|
+
}
|
|
143
|
+
fromOut := r.outputPathForSource(fromSource)
|
|
144
|
+
targetOut := r.outputPathForSource(targetSource)
|
|
145
|
+
if fromOut == "" || targetOut == "" {
|
|
146
|
+
return specifier, false
|
|
147
|
+
}
|
|
148
|
+
rel, err := filepath.Rel(filepath.Dir(fromOut), targetOut)
|
|
149
|
+
if err != nil {
|
|
150
|
+
return specifier, false
|
|
151
|
+
}
|
|
152
|
+
rel = filepath.ToSlash(rel)
|
|
153
|
+
if !strings.HasPrefix(rel, ".") {
|
|
154
|
+
rel = "./" + rel
|
|
155
|
+
}
|
|
156
|
+
return rel, true
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
func (r *pathsRewriter) resolveSource(specifier string) (string, bool) {
|
|
160
|
+
for _, pattern := range r.patterns {
|
|
161
|
+
star, ok := matchPattern(pattern.pattern, specifier)
|
|
162
|
+
if !ok {
|
|
163
|
+
continue
|
|
164
|
+
}
|
|
165
|
+
for _, target := range pattern.targets {
|
|
166
|
+
candidate := strings.Replace(target, "*", star, 1)
|
|
167
|
+
resolved := normalizePath(filepath.Join(r.basePath, candidate))
|
|
168
|
+
if source, ok := r.lookupSource(resolved); ok {
|
|
169
|
+
return source, true
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return "", false
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
func (r *pathsRewriter) lookupSource(candidate string) (string, bool) {
|
|
177
|
+
if source, ok := r.sourceFiles[normalizePath(candidate)]; ok {
|
|
178
|
+
return source, true
|
|
179
|
+
}
|
|
180
|
+
stem := stripKnownSourceExtension(normalizePath(candidate))
|
|
181
|
+
if source, ok := r.sourceFiles[stem]; ok {
|
|
182
|
+
return source, true
|
|
183
|
+
}
|
|
184
|
+
for _, ext := range []string{".ts", ".tsx", ".mts", ".cts"} {
|
|
185
|
+
if source, ok := r.sourceFiles[stem+ext]; ok {
|
|
186
|
+
return source, true
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
for _, ext := range []string{".ts", ".tsx", ".mts", ".cts"} {
|
|
190
|
+
if source, ok := r.sourceFiles[normalizePath(filepath.Join(stem, "index"+ext))]; ok {
|
|
191
|
+
return source, true
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return "", false
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
func (r *pathsRewriter) outputPathForSource(source string) string {
|
|
198
|
+
if r.outDir == "" || r.rootDir == "" {
|
|
199
|
+
return ""
|
|
200
|
+
}
|
|
201
|
+
rel, err := filepath.Rel(r.rootDir, source)
|
|
202
|
+
if err != nil || isOutsideRelativePath(rel) {
|
|
203
|
+
return ""
|
|
204
|
+
}
|
|
205
|
+
return normalizePath(filepath.Join(r.outDir, replaceSourceExtension(rel, emittedJavaScriptExtension(rel))))
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
func emittedJavaScriptExtension(source string) string {
|
|
209
|
+
switch strings.ToLower(filepath.Ext(source)) {
|
|
210
|
+
case ".mts":
|
|
211
|
+
return ".mjs"
|
|
212
|
+
case ".cts":
|
|
213
|
+
return ".cjs"
|
|
214
|
+
default:
|
|
215
|
+
return ".js"
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
func matchPattern(pattern string, specifier string) (string, bool) {
|
|
220
|
+
if !strings.Contains(pattern, "*") {
|
|
221
|
+
return "", pattern == specifier
|
|
222
|
+
}
|
|
223
|
+
parts := strings.SplitN(pattern, "*", 2)
|
|
224
|
+
if !strings.HasPrefix(specifier, parts[0]) || !strings.HasSuffix(specifier, parts[1]) {
|
|
225
|
+
return "", false
|
|
226
|
+
}
|
|
227
|
+
return specifier[len(parts[0]) : len(specifier)-len(parts[1])], true
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
func patternRank(pattern string) int {
|
|
231
|
+
return len(strings.ReplaceAll(pattern, "*", ""))
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
func optionalPath(value string, cwd string) string {
|
|
235
|
+
if value == "" {
|
|
236
|
+
return ""
|
|
237
|
+
}
|
|
238
|
+
if filepath.IsAbs(value) {
|
|
239
|
+
return normalizePath(value)
|
|
240
|
+
}
|
|
241
|
+
return normalizePath(filepath.Join(cwd, value))
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
func commonSourceDir(files []*shimast.SourceFile) string {
|
|
245
|
+
if len(files) == 0 {
|
|
246
|
+
return ""
|
|
247
|
+
}
|
|
248
|
+
common := normalizePath(filepath.Dir(files[0].FileName()))
|
|
249
|
+
for _, file := range files[1:] {
|
|
250
|
+
dir := normalizePath(filepath.Dir(file.FileName()))
|
|
251
|
+
for common != "" && !strings.HasPrefix(dir+"/", common+"/") {
|
|
252
|
+
next := filepath.Dir(common)
|
|
253
|
+
if next == common {
|
|
254
|
+
return common
|
|
255
|
+
}
|
|
256
|
+
common = normalizePath(next)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return common
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
func normalizePath(value string) string {
|
|
263
|
+
if value == "" {
|
|
264
|
+
return ""
|
|
265
|
+
}
|
|
266
|
+
return filepath.ToSlash(filepath.Clean(value))
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
func isOutsideRelativePath(rel string) bool {
|
|
270
|
+
return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
func stripKnownSourceExtension(value string) string {
|
|
274
|
+
lower := strings.ToLower(value)
|
|
275
|
+
for _, ext := range []string{".d.ts", ".d.mts", ".d.cts", ".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"} {
|
|
276
|
+
if strings.HasSuffix(lower, ext) {
|
|
277
|
+
return value[:len(value)-len(ext)]
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return strings.TrimSuffix(value, filepath.Ext(value))
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
func replaceSourceExtension(value string, ext string) string {
|
|
284
|
+
return stripKnownSourceExtension(filepath.ToSlash(value)) + ext
|
|
285
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
5
|
+
shimprinter "github.com/microsoft/typescript-go/shim/printer"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
const nestiaKindColonToken = shimast.KindQuestionToken + 1
|
|
9
|
+
|
|
10
|
+
func emitNestiaWithIdentifierSubstitutions(
|
|
11
|
+
node *shimast.Node,
|
|
12
|
+
sourceFile *shimast.SourceFile,
|
|
13
|
+
substitutions map[string]string,
|
|
14
|
+
) string {
|
|
15
|
+
node = stripNestiaTypeSyntax(node)
|
|
16
|
+
node = rewriteNestiaIdentifiers(node, substitutions)
|
|
17
|
+
normalizeNestiaSyntheticTokens(node)
|
|
18
|
+
return emitNestiaNode(node, sourceFile)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func emitNestiaPreservingTypesWithIdentifierSubstitutions(
|
|
22
|
+
node *shimast.Node,
|
|
23
|
+
sourceFile *shimast.SourceFile,
|
|
24
|
+
substitutions map[string]string,
|
|
25
|
+
) string {
|
|
26
|
+
node = rewriteNestiaIdentifiers(node, substitutions)
|
|
27
|
+
normalizeNestiaSyntheticTokens(node)
|
|
28
|
+
return emitNestiaNode(node, sourceFile)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func emitNestiaNode(node *shimast.Node, sourceFile *shimast.SourceFile) string {
|
|
32
|
+
return shimprinter.NewPrinter(shimprinter.PrinterOptions{
|
|
33
|
+
RemoveComments: true,
|
|
34
|
+
NewLine: 2,
|
|
35
|
+
}, shimprinter.PrintHandlers{}, nil).Emit(node, sourceFile)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
func stripNestiaTypeSyntax(node *shimast.Node) *shimast.Node {
|
|
39
|
+
if node == nil {
|
|
40
|
+
return nil
|
|
41
|
+
}
|
|
42
|
+
factory := shimast.NewNodeFactory(shimast.NodeFactoryHooks{})
|
|
43
|
+
var visitor *shimast.NodeVisitor
|
|
44
|
+
visitor = shimast.NewNodeVisitor(func(current *shimast.Node) *shimast.Node {
|
|
45
|
+
if current == nil {
|
|
46
|
+
return nil
|
|
47
|
+
}
|
|
48
|
+
switch current.Kind {
|
|
49
|
+
case shimast.KindAsExpression, shimast.KindSatisfiesExpression, shimast.KindTypeAssertionExpression, shimast.KindNonNullExpression:
|
|
50
|
+
return visitor.VisitNode(current.Expression())
|
|
51
|
+
case shimast.KindVariableDeclaration:
|
|
52
|
+
decl := current.AsVariableDeclaration()
|
|
53
|
+
return factory.UpdateVariableDeclaration(
|
|
54
|
+
decl,
|
|
55
|
+
visitor.VisitNode(decl.Name()),
|
|
56
|
+
nil,
|
|
57
|
+
nil,
|
|
58
|
+
visitor.VisitNode(decl.Initializer),
|
|
59
|
+
)
|
|
60
|
+
case shimast.KindParameter:
|
|
61
|
+
parameter := current.AsParameterDeclaration()
|
|
62
|
+
return factory.UpdateParameterDeclaration(
|
|
63
|
+
parameter,
|
|
64
|
+
visitor.VisitModifiers(parameter.Modifiers()),
|
|
65
|
+
visitor.VisitNode(parameter.DotDotDotToken),
|
|
66
|
+
visitor.VisitNode(parameter.Name()),
|
|
67
|
+
nil,
|
|
68
|
+
nil,
|
|
69
|
+
visitor.VisitNode(parameter.Initializer),
|
|
70
|
+
)
|
|
71
|
+
case shimast.KindArrowFunction:
|
|
72
|
+
arrow := current.AsArrowFunction()
|
|
73
|
+
return factory.UpdateArrowFunction(
|
|
74
|
+
arrow,
|
|
75
|
+
visitor.VisitModifiers(arrow.Modifiers()),
|
|
76
|
+
nil,
|
|
77
|
+
visitor.VisitNodes(arrow.Parameters),
|
|
78
|
+
nil,
|
|
79
|
+
nil,
|
|
80
|
+
visitor.VisitNode(arrow.EqualsGreaterThanToken),
|
|
81
|
+
visitor.VisitNode(arrow.Body),
|
|
82
|
+
)
|
|
83
|
+
case shimast.KindCallExpression:
|
|
84
|
+
call := current.AsCallExpression()
|
|
85
|
+
return factory.UpdateCallExpression(
|
|
86
|
+
call,
|
|
87
|
+
visitor.VisitNode(call.Expression),
|
|
88
|
+
visitor.VisitNode(call.QuestionDotToken),
|
|
89
|
+
nil,
|
|
90
|
+
visitor.VisitNodes(call.Arguments),
|
|
91
|
+
call.Flags,
|
|
92
|
+
)
|
|
93
|
+
case shimast.KindNewExpression:
|
|
94
|
+
expr := current.AsNewExpression()
|
|
95
|
+
return factory.UpdateNewExpression(
|
|
96
|
+
expr,
|
|
97
|
+
visitor.VisitNode(expr.Expression),
|
|
98
|
+
nil,
|
|
99
|
+
visitor.VisitNodes(expr.Arguments),
|
|
100
|
+
)
|
|
101
|
+
default:
|
|
102
|
+
return visitor.VisitEachChild(current)
|
|
103
|
+
}
|
|
104
|
+
}, factory, shimast.NodeVisitorHooks{})
|
|
105
|
+
return visitor.VisitNode(node)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
func rewriteNestiaIdentifiers(
|
|
109
|
+
node *shimast.Node,
|
|
110
|
+
substitutions map[string]string,
|
|
111
|
+
) *shimast.Node {
|
|
112
|
+
if node == nil || len(substitutions) == 0 {
|
|
113
|
+
return node
|
|
114
|
+
}
|
|
115
|
+
factory := shimast.NewNodeFactory(shimast.NodeFactoryHooks{})
|
|
116
|
+
var visitor *shimast.NodeVisitor
|
|
117
|
+
visitor = shimast.NewNodeVisitor(func(current *shimast.Node) *shimast.Node {
|
|
118
|
+
if current == nil {
|
|
119
|
+
return nil
|
|
120
|
+
}
|
|
121
|
+
switch current.Kind {
|
|
122
|
+
case shimast.KindIdentifier:
|
|
123
|
+
if replacement, ok := substitutions[current.Text()]; ok {
|
|
124
|
+
return rewriteNestiaIdentifierExpression(factory, replacement)
|
|
125
|
+
}
|
|
126
|
+
return current
|
|
127
|
+
case shimast.KindVariableDeclaration:
|
|
128
|
+
decl := current.AsVariableDeclaration()
|
|
129
|
+
return factory.UpdateVariableDeclaration(
|
|
130
|
+
decl,
|
|
131
|
+
decl.Name(),
|
|
132
|
+
nil,
|
|
133
|
+
nil,
|
|
134
|
+
visitor.VisitNode(decl.Initializer),
|
|
135
|
+
)
|
|
136
|
+
case shimast.KindParameter:
|
|
137
|
+
parameter := current.AsParameterDeclaration()
|
|
138
|
+
return factory.UpdateParameterDeclaration(
|
|
139
|
+
parameter,
|
|
140
|
+
parameter.Modifiers(),
|
|
141
|
+
parameter.DotDotDotToken,
|
|
142
|
+
parameter.Name(),
|
|
143
|
+
nil,
|
|
144
|
+
nil,
|
|
145
|
+
visitor.VisitNode(parameter.Initializer),
|
|
146
|
+
)
|
|
147
|
+
case shimast.KindPropertyAssignment:
|
|
148
|
+
assignment := current.AsPropertyAssignment()
|
|
149
|
+
return factory.UpdatePropertyAssignment(
|
|
150
|
+
assignment,
|
|
151
|
+
assignment.Modifiers(),
|
|
152
|
+
assignment.Name(),
|
|
153
|
+
assignment.PostfixToken,
|
|
154
|
+
nil,
|
|
155
|
+
visitor.VisitNode(assignment.Initializer),
|
|
156
|
+
)
|
|
157
|
+
case shimast.KindShorthandPropertyAssignment:
|
|
158
|
+
assignment := current.AsShorthandPropertyAssignment()
|
|
159
|
+
name := assignment.Name()
|
|
160
|
+
if name != nil && name.Kind == shimast.KindIdentifier {
|
|
161
|
+
if replacement, ok := substitutions[name.Text()]; ok &&
|
|
162
|
+
assignment.ObjectAssignmentInitializer == nil {
|
|
163
|
+
return factory.NewPropertyAssignment(
|
|
164
|
+
assignment.Modifiers(),
|
|
165
|
+
name,
|
|
166
|
+
assignment.PostfixToken,
|
|
167
|
+
nil,
|
|
168
|
+
rewriteNestiaIdentifierExpression(factory, replacement),
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return factory.UpdateShorthandPropertyAssignment(
|
|
173
|
+
assignment,
|
|
174
|
+
assignment.Modifiers(),
|
|
175
|
+
name,
|
|
176
|
+
assignment.PostfixToken,
|
|
177
|
+
nil,
|
|
178
|
+
nil,
|
|
179
|
+
visitor.VisitNode(assignment.ObjectAssignmentInitializer),
|
|
180
|
+
)
|
|
181
|
+
case shimast.KindPropertyAccessExpression:
|
|
182
|
+
access := current.AsPropertyAccessExpression()
|
|
183
|
+
return factory.UpdatePropertyAccessExpression(
|
|
184
|
+
access,
|
|
185
|
+
visitor.VisitNode(access.Expression),
|
|
186
|
+
access.QuestionDotToken,
|
|
187
|
+
access.Name(),
|
|
188
|
+
access.Flags,
|
|
189
|
+
)
|
|
190
|
+
default:
|
|
191
|
+
return visitor.VisitEachChild(current)
|
|
192
|
+
}
|
|
193
|
+
}, factory, shimast.NodeVisitorHooks{})
|
|
194
|
+
return visitor.VisitNode(node)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
func rewriteNestiaIdentifierExpression(
|
|
198
|
+
factory *shimast.NodeFactory,
|
|
199
|
+
replacement string,
|
|
200
|
+
) *shimast.Node {
|
|
201
|
+
parts := []string{}
|
|
202
|
+
start := 0
|
|
203
|
+
for i := 0; i <= len(replacement); i++ {
|
|
204
|
+
if i == len(replacement) || replacement[i] == '.' {
|
|
205
|
+
if start < i {
|
|
206
|
+
parts = append(parts, replacement[start:i])
|
|
207
|
+
}
|
|
208
|
+
start = i + 1
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if len(parts) == 0 {
|
|
212
|
+
return factory.NewIdentifier(replacement)
|
|
213
|
+
}
|
|
214
|
+
output := factory.NewIdentifier(parts[0])
|
|
215
|
+
for _, part := range parts[1:] {
|
|
216
|
+
output = factory.NewPropertyAccessExpression(
|
|
217
|
+
output,
|
|
218
|
+
nil,
|
|
219
|
+
factory.NewIdentifier(part),
|
|
220
|
+
shimast.NodeFlagsNone,
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
return output
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
func normalizeNestiaSyntheticTokens(node *shimast.Node) {
|
|
227
|
+
if node == nil {
|
|
228
|
+
return
|
|
229
|
+
}
|
|
230
|
+
if node.Kind == shimast.KindConditionalExpression {
|
|
231
|
+
conditional := node.AsConditionalExpression()
|
|
232
|
+
factory := shimast.NewNodeFactory(shimast.NodeFactoryHooks{})
|
|
233
|
+
if conditional.QuestionToken == nil {
|
|
234
|
+
conditional.QuestionToken = factory.NewToken(shimast.KindQuestionToken)
|
|
235
|
+
}
|
|
236
|
+
if conditional.ColonToken == nil {
|
|
237
|
+
conditional.ColonToken = factory.NewToken(nestiaKindColonToken)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
node.ForEachChild(func(child *shimast.Node) bool {
|
|
241
|
+
normalizeNestiaSyntheticTokens(child)
|
|
242
|
+
return false
|
|
243
|
+
})
|
|
244
|
+
}
|