ttsc 0.7.3 → 0.8.0-dev.20260505
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/README.md +3 -4
- package/driver/rewrite.go +41 -0
- package/lib/compiler/internal/runBuild.js +47 -49
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/transformProjectInMemory.js +44 -4
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/launcher/internal/runTtsc.js +19 -1
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/plugin/internal/buildSourcePlugin.js +6 -0
- package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/loadProjectPlugins.js +55 -2
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
- package/lib/structures/ITtscPlugin.d.ts +19 -3
- package/lib/structures/ITtscPlugin.js +4 -0
- package/lib/structures/ITtscPlugin.js.map +1 -1
- package/lib/structures/TtscPluginStage.d.ts +4 -10
- package/lib/structures/internal/ITtscLoadedNativePlugin.d.ts +5 -0
- package/package.json +11 -10
- package/shim/ast/lint.go +1 -0
- package/shim/ast/shim.go +1 -0
- package/shim/compiler/emit_hooks.go +494 -0
- package/shim/core/shim.go +3 -0
- package/src/compiler/internal/runBuild.ts +54 -85
- package/src/compiler/internal/transformProjectInMemory.ts +51 -6
- package/src/launcher/internal/runTtsc.ts +17 -1
- package/src/plugin/internal/buildSourcePlugin.ts +23 -0
- package/src/plugin/internal/loadProjectPlugins.ts +81 -2
- package/src/structures/ITtscPlugin.ts +30 -3
- package/src/structures/TtscPluginStage.ts +4 -10
- package/src/structures/internal/ITtscLoadedNativePlugin.ts +5 -0
- package/test/compiler.test.ts +3 -3
- package/test/tsgo.test.ts +9 -6
- package/utility/host.go +707 -0
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
package compiler
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
|
|
6
|
+
"github.com/microsoft/typescript-go/internal/ast"
|
|
7
|
+
"github.com/microsoft/typescript-go/internal/binder"
|
|
8
|
+
innercompiler "github.com/microsoft/typescript-go/internal/compiler"
|
|
9
|
+
"github.com/microsoft/typescript-go/internal/core"
|
|
10
|
+
"github.com/microsoft/typescript-go/internal/diagnostics"
|
|
11
|
+
"github.com/microsoft/typescript-go/internal/module"
|
|
12
|
+
"github.com/microsoft/typescript-go/internal/outputpaths"
|
|
13
|
+
"github.com/microsoft/typescript-go/internal/packagejson"
|
|
14
|
+
"github.com/microsoft/typescript-go/internal/printer"
|
|
15
|
+
"github.com/microsoft/typescript-go/internal/sourcemap"
|
|
16
|
+
"github.com/microsoft/typescript-go/internal/stringutil"
|
|
17
|
+
"github.com/microsoft/typescript-go/internal/symlinks"
|
|
18
|
+
"github.com/microsoft/typescript-go/internal/transformers"
|
|
19
|
+
"github.com/microsoft/typescript-go/internal/transformers/declarations"
|
|
20
|
+
"github.com/microsoft/typescript-go/internal/transformers/estransforms"
|
|
21
|
+
"github.com/microsoft/typescript-go/internal/transformers/inliners"
|
|
22
|
+
"github.com/microsoft/typescript-go/internal/transformers/jsxtransforms"
|
|
23
|
+
"github.com/microsoft/typescript-go/internal/transformers/moduletransforms"
|
|
24
|
+
"github.com/microsoft/typescript-go/internal/transformers/tstransforms"
|
|
25
|
+
"github.com/microsoft/typescript-go/internal/tsoptions"
|
|
26
|
+
"github.com/microsoft/typescript-go/internal/tspath"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
type EmitContext = printer.EmitContext
|
|
30
|
+
|
|
31
|
+
type EmitSourceFileHook func(context *EmitContext, file *ast.SourceFile) *ast.SourceFile
|
|
32
|
+
|
|
33
|
+
type EmitHooks struct {
|
|
34
|
+
BeforePrintDeclaration EmitSourceFileHook
|
|
35
|
+
BeforePrintJS EmitSourceFileHook
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type hookEmitHost struct {
|
|
39
|
+
program *innercompiler.Program
|
|
40
|
+
emitResolver printer.EmitResolver
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type hookEmitter struct {
|
|
44
|
+
host *hookEmitHost
|
|
45
|
+
emitOnly innercompiler.EmitOnly
|
|
46
|
+
emitResult innercompiler.EmitResult
|
|
47
|
+
hooks EmitHooks
|
|
48
|
+
paths *outputpaths.OutputPaths
|
|
49
|
+
sourceFile *ast.SourceFile
|
|
50
|
+
writeFile innercompiler.WriteFile
|
|
51
|
+
writer printer.EmitTextWriter
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
func EmitWithHooks(ctx context.Context, program *innercompiler.Program, options innercompiler.EmitOptions, hooks EmitHooks) *innercompiler.EmitResult {
|
|
55
|
+
if program == nil {
|
|
56
|
+
return nil
|
|
57
|
+
}
|
|
58
|
+
if options.EmitOnly != innercompiler.EmitOnlyForcedDts {
|
|
59
|
+
result := HandleNoEmitOnError(ctx, program, options.TargetSourceFile)
|
|
60
|
+
if result != nil || ctx.Err() != nil {
|
|
61
|
+
return result
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
var results []*innercompiler.EmitResult
|
|
65
|
+
newLine := program.Options().NewLine.GetNewLineCharacter()
|
|
66
|
+
for _, sourceFile := range hookSourceFilesToEmit(program, options.TargetSourceFile, options.EmitOnly == innercompiler.EmitOnlyForcedDts) {
|
|
67
|
+
host, done := newHookEmitHost(ctx, program, sourceFile)
|
|
68
|
+
emitter := &hookEmitter{
|
|
69
|
+
host: host,
|
|
70
|
+
emitOnly: options.EmitOnly,
|
|
71
|
+
hooks: hooks,
|
|
72
|
+
paths: outputpaths.GetOutputPathsFor(sourceFile, host.Options(), host, options.EmitOnly == innercompiler.EmitOnlyForcedDts),
|
|
73
|
+
sourceFile: sourceFile,
|
|
74
|
+
writeFile: options.WriteFile,
|
|
75
|
+
writer: printer.NewTextWriter(newLine, 0),
|
|
76
|
+
}
|
|
77
|
+
emitter.emit()
|
|
78
|
+
done()
|
|
79
|
+
results = append(results, &emitter.emitResult)
|
|
80
|
+
}
|
|
81
|
+
return CombineEmitResults(results)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
func hookSourceFilesToEmit(program *innercompiler.Program, target *ast.SourceFile, forceDtsEmit bool) []*ast.SourceFile {
|
|
85
|
+
if target != nil {
|
|
86
|
+
if program.SourceFileMayBeEmitted(target, forceDtsEmit) {
|
|
87
|
+
return []*ast.SourceFile{target}
|
|
88
|
+
}
|
|
89
|
+
return nil
|
|
90
|
+
}
|
|
91
|
+
var out []*ast.SourceFile
|
|
92
|
+
for _, sourceFile := range program.SourceFiles() {
|
|
93
|
+
if program.SourceFileMayBeEmitted(sourceFile, forceDtsEmit) {
|
|
94
|
+
out = append(out, sourceFile)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return out
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
func newHookEmitHost(ctx context.Context, program *innercompiler.Program, file *ast.SourceFile) (*hookEmitHost, func()) {
|
|
101
|
+
checker, done := program.GetTypeCheckerForFile(ctx, file)
|
|
102
|
+
return &hookEmitHost{
|
|
103
|
+
program: program,
|
|
104
|
+
emitResolver: checker.GetEmitResolver(),
|
|
105
|
+
}, done
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
func (e *hookEmitter) emit() {
|
|
109
|
+
e.emitJSFile(e.sourceFile, e.paths.JsFilePath(), e.paths.SourceMapFilePath())
|
|
110
|
+
e.emitDeclarationFile(e.sourceFile, e.paths.DeclarationFilePath(), e.paths.DeclarationMapPath())
|
|
111
|
+
e.emitResult.Diagnostics = e.emitterDiagnostics()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
func (e *hookEmitter) emitterDiagnostics() []*ast.Diagnostic {
|
|
115
|
+
return e.emitResult.Diagnostics
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
func (e *hookEmitter) addDiagnostic(diag *ast.Diagnostic) {
|
|
119
|
+
e.emitResult.Diagnostics = append(e.emitResult.Diagnostics, diag)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
func (e *hookEmitter) runScriptTransformers(emitContext *printer.EmitContext, sourceFile *ast.SourceFile) *ast.SourceFile {
|
|
123
|
+
for _, transformer := range hookScriptTransformers(emitContext, e.host, sourceFile) {
|
|
124
|
+
sourceFile = transformer.TransformSourceFile(sourceFile)
|
|
125
|
+
}
|
|
126
|
+
return sourceFile
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
func (e *hookEmitter) runDeclarationTransformers(emitContext *printer.EmitContext, sourceFile *ast.SourceFile, declarationFilePath, declarationMapPath string) (*ast.SourceFile, []*ast.Diagnostic) {
|
|
130
|
+
transform := declarations.NewDeclarationTransformer(e.host, emitContext, e.host.Options(), declarationFilePath, declarationMapPath)
|
|
131
|
+
sourceFile = transform.TransformSourceFile(sourceFile)
|
|
132
|
+
return sourceFile, transform.GetDiagnostics()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func (e *hookEmitter) emitJSFile(sourceFile *ast.SourceFile, jsFilePath string, sourceMapFilePath string) {
|
|
136
|
+
options := e.host.Options()
|
|
137
|
+
if sourceFile == nil || e.emitOnly != innercompiler.EmitAll && e.emitOnly != innercompiler.EmitOnlyJs || len(jsFilePath) == 0 {
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
if options.NoEmit == core.TSTrue || e.host.IsEmitBlocked(jsFilePath) {
|
|
141
|
+
e.emitResult.EmitSkipped = true
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
emitContext, putEmitContext := printer.GetEmitContext()
|
|
145
|
+
defer putEmitContext()
|
|
146
|
+
sourceFile = e.runScriptTransformers(emitContext, sourceFile)
|
|
147
|
+
if e.hooks.BeforePrintJS != nil {
|
|
148
|
+
sourceFile = e.hooks.BeforePrintJS(emitContext, sourceFile)
|
|
149
|
+
}
|
|
150
|
+
printerOptions := printer.PrinterOptions{
|
|
151
|
+
RemoveComments: options.RemoveComments.IsTrue(),
|
|
152
|
+
NewLine: options.NewLine,
|
|
153
|
+
NoEmitHelpers: options.NoEmitHelpers.IsTrue(),
|
|
154
|
+
SourceMap: options.SourceMap.IsTrue(),
|
|
155
|
+
InlineSourceMap: options.InlineSourceMap.IsTrue(),
|
|
156
|
+
InlineSources: options.InlineSources.IsTrue(),
|
|
157
|
+
Target: options.Target,
|
|
158
|
+
}
|
|
159
|
+
p := printer.NewPrinter(printerOptions, printer.PrintHandlers{}, emitContext)
|
|
160
|
+
e.printSourceFile(jsFilePath, sourceMapFilePath, sourceFile, p, hookShouldEmitSourceMaps(options, sourceFile))
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
func (e *hookEmitter) emitDeclarationFile(sourceFile *ast.SourceFile, declarationFilePath string, declarationMapPath string) {
|
|
164
|
+
options := e.host.Options()
|
|
165
|
+
if sourceFile == nil || e.emitOnly == innercompiler.EmitOnlyJs || len(declarationFilePath) == 0 {
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
if e.emitOnly != innercompiler.EmitOnlyForcedDts && (options.NoEmit == core.TSTrue || e.host.IsEmitBlocked(declarationFilePath)) {
|
|
169
|
+
e.emitResult.EmitSkipped = true
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
emitContext, putEmitContext := printer.GetEmitContext()
|
|
173
|
+
defer putEmitContext()
|
|
174
|
+
sourceFile, diags := e.runDeclarationTransformers(emitContext, sourceFile, declarationFilePath, declarationMapPath)
|
|
175
|
+
if e.hooks.BeforePrintDeclaration != nil {
|
|
176
|
+
sourceFile = e.hooks.BeforePrintDeclaration(emitContext, sourceFile)
|
|
177
|
+
}
|
|
178
|
+
printerOptions := printer.PrinterOptions{
|
|
179
|
+
RemoveComments: options.RemoveComments.IsTrue(),
|
|
180
|
+
OnlyPrintJSDocStyle: true,
|
|
181
|
+
NewLine: options.NewLine,
|
|
182
|
+
NoEmitHelpers: options.NoEmitHelpers.IsTrue(),
|
|
183
|
+
SourceMap: options.DeclarationMap.IsTrue(),
|
|
184
|
+
InlineSourceMap: options.InlineSourceMap.IsTrue(),
|
|
185
|
+
InlineSources: options.InlineSources.IsTrue(),
|
|
186
|
+
}
|
|
187
|
+
p := printer.NewPrinter(printerOptions, printer.PrintHandlers{}, emitContext)
|
|
188
|
+
for _, diag := range diags {
|
|
189
|
+
e.addDiagnostic(diag)
|
|
190
|
+
}
|
|
191
|
+
e.printSourceFile(declarationFilePath, declarationMapPath, sourceFile, p, e.emitOnly != innercompiler.EmitOnlyForcedDts && hookShouldEmitDeclarationSourceMaps(options, sourceFile))
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
func (e *hookEmitter) printSourceFile(filePath string, sourceMapFilePath string, sourceFile *ast.SourceFile, printer_ *printer.Printer, shouldEmitSourceMaps bool) {
|
|
195
|
+
options := e.host.Options()
|
|
196
|
+
var sourceMapGenerator *sourcemap.Generator
|
|
197
|
+
if shouldEmitSourceMaps {
|
|
198
|
+
sourceMapGenerator = sourcemap.NewGenerator(
|
|
199
|
+
tspath.GetBaseFileName(tspath.NormalizeSlashes(filePath)),
|
|
200
|
+
hookSourceRoot(options),
|
|
201
|
+
e.sourceMapDirectory(options, filePath, sourceFile),
|
|
202
|
+
tspath.ComparePathsOptions{
|
|
203
|
+
UseCaseSensitiveFileNames: e.host.UseCaseSensitiveFileNames(),
|
|
204
|
+
CurrentDirectory: e.host.GetCurrentDirectory(),
|
|
205
|
+
},
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
printer_.Write(sourceFile.AsNode(), sourceFile, e.writer, sourceMapGenerator)
|
|
209
|
+
sourceMapURLPos := -1
|
|
210
|
+
if sourceMapGenerator != nil {
|
|
211
|
+
if options.SourceMap.IsTrue() || options.InlineSourceMap.IsTrue() || options.GetAreDeclarationMapsEnabled() {
|
|
212
|
+
e.emitResult.SourceMaps = append(e.emitResult.SourceMaps, &innercompiler.SourceMapEmitResult{
|
|
213
|
+
InputSourceFileNames: sourceMapGenerator.Sources(),
|
|
214
|
+
SourceMap: sourceMapGenerator.RawSourceMap(),
|
|
215
|
+
GeneratedFile: filePath,
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
sourceMappingURL := e.sourceMappingURL(options, sourceMapGenerator, filePath, sourceMapFilePath, sourceFile)
|
|
219
|
+
if len(sourceMappingURL) > 0 {
|
|
220
|
+
if !e.writer.IsAtStartOfLine() {
|
|
221
|
+
e.writer.RawWrite(core.IfElse(options.NewLine == core.NewLineKindCRLF, "\r\n", "\n"))
|
|
222
|
+
}
|
|
223
|
+
sourceMapURLPos = e.writer.GetTextPos()
|
|
224
|
+
e.writer.WriteComment("//# sourceMappingURL=")
|
|
225
|
+
e.writer.WriteComment(sourceMappingURL)
|
|
226
|
+
}
|
|
227
|
+
if len(sourceMapFilePath) > 0 {
|
|
228
|
+
sourceMap := sourceMapGenerator.String()
|
|
229
|
+
if err := e.writeText(sourceMapFilePath, sourceMap, nil); err != nil {
|
|
230
|
+
e.addDiagnostic(ast.NewCompilerDiagnostic(diagnostics.Could_not_write_file_0_Colon_1, filePath, err.Error()))
|
|
231
|
+
} else {
|
|
232
|
+
e.emitResult.EmittedFiles = append(e.emitResult.EmittedFiles, sourceMapFilePath)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} else {
|
|
236
|
+
e.writer.WriteLine()
|
|
237
|
+
}
|
|
238
|
+
text := e.writer.String()
|
|
239
|
+
if options.EmitBOM.IsTrue() {
|
|
240
|
+
text = stringutil.AddUTF8ByteOrderMark(text)
|
|
241
|
+
}
|
|
242
|
+
data := &innercompiler.WriteFileData{
|
|
243
|
+
SourceMapUrlPos: sourceMapURLPos,
|
|
244
|
+
Diagnostics: e.emitterDiagnostics(),
|
|
245
|
+
}
|
|
246
|
+
err := e.writeText(filePath, text, data)
|
|
247
|
+
skippedDtsWrite := data.SkippedDtsWrite
|
|
248
|
+
if err != nil {
|
|
249
|
+
e.addDiagnostic(ast.NewCompilerDiagnostic(diagnostics.Could_not_write_file_0_Colon_1, filePath, err.Error()))
|
|
250
|
+
} else if !skippedDtsWrite {
|
|
251
|
+
e.emitResult.EmittedFiles = append(e.emitResult.EmittedFiles, filePath)
|
|
252
|
+
}
|
|
253
|
+
e.writer.Clear()
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
func (e *hookEmitter) writeText(fileName string, text string, data *innercompiler.WriteFileData) error {
|
|
257
|
+
if e.writeFile != nil {
|
|
258
|
+
return e.writeFile(fileName, text, data)
|
|
259
|
+
}
|
|
260
|
+
return e.host.WriteFile(fileName, text)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
func (e *hookEmitter) sourceMapDirectory(options *core.CompilerOptions, filePath string, sourceFile *ast.SourceFile) string {
|
|
264
|
+
if len(options.SourceRoot) > 0 {
|
|
265
|
+
return e.host.CommonSourceDirectory()
|
|
266
|
+
}
|
|
267
|
+
if len(options.MapRoot) > 0 {
|
|
268
|
+
sourceMapDir := tspath.NormalizeSlashes(options.MapRoot)
|
|
269
|
+
if sourceFile != nil {
|
|
270
|
+
sourceMapDir = tspath.GetDirectoryPath(outputpaths.GetSourceFilePathInNewDir(
|
|
271
|
+
sourceFile.FileName(),
|
|
272
|
+
sourceMapDir,
|
|
273
|
+
e.host.GetCurrentDirectory(),
|
|
274
|
+
e.host.CommonSourceDirectory(),
|
|
275
|
+
e.host.UseCaseSensitiveFileNames(),
|
|
276
|
+
))
|
|
277
|
+
}
|
|
278
|
+
if tspath.GetRootLength(sourceMapDir) == 0 {
|
|
279
|
+
sourceMapDir = tspath.CombinePaths(e.host.CommonSourceDirectory(), sourceMapDir)
|
|
280
|
+
}
|
|
281
|
+
return sourceMapDir
|
|
282
|
+
}
|
|
283
|
+
return tspath.GetDirectoryPath(tspath.NormalizePath(filePath))
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
func (e *hookEmitter) sourceMappingURL(options *core.CompilerOptions, sourceMapGenerator *sourcemap.Generator, filePath string, sourceMapFilePath string, sourceFile *ast.SourceFile) string {
|
|
287
|
+
if options.InlineSourceMap.IsTrue() {
|
|
288
|
+
return sourceMapGenerator.Base64DataURL()
|
|
289
|
+
}
|
|
290
|
+
sourceMapFile := tspath.GetBaseFileName(tspath.NormalizeSlashes(sourceMapFilePath))
|
|
291
|
+
if len(options.MapRoot) > 0 {
|
|
292
|
+
sourceMapDir := tspath.NormalizeSlashes(options.MapRoot)
|
|
293
|
+
if sourceFile != nil {
|
|
294
|
+
sourceMapDir = tspath.GetDirectoryPath(outputpaths.GetSourceFilePathInNewDir(
|
|
295
|
+
sourceFile.FileName(),
|
|
296
|
+
sourceMapDir,
|
|
297
|
+
e.host.GetCurrentDirectory(),
|
|
298
|
+
e.host.CommonSourceDirectory(),
|
|
299
|
+
e.host.UseCaseSensitiveFileNames(),
|
|
300
|
+
))
|
|
301
|
+
}
|
|
302
|
+
if tspath.GetRootLength(sourceMapDir) == 0 {
|
|
303
|
+
sourceMapDir = tspath.CombinePaths(e.host.CommonSourceDirectory(), sourceMapDir)
|
|
304
|
+
return stringutil.EncodeURI(
|
|
305
|
+
tspath.GetRelativePathToDirectoryOrUrl(
|
|
306
|
+
tspath.GetDirectoryPath(tspath.NormalizePath(filePath)),
|
|
307
|
+
tspath.CombinePaths(sourceMapDir, sourceMapFile),
|
|
308
|
+
true,
|
|
309
|
+
tspath.ComparePathsOptions{
|
|
310
|
+
UseCaseSensitiveFileNames: e.host.UseCaseSensitiveFileNames(),
|
|
311
|
+
CurrentDirectory: e.host.GetCurrentDirectory(),
|
|
312
|
+
},
|
|
313
|
+
),
|
|
314
|
+
)
|
|
315
|
+
}
|
|
316
|
+
return stringutil.EncodeURI(tspath.CombinePaths(sourceMapDir, sourceMapFile))
|
|
317
|
+
}
|
|
318
|
+
return stringutil.EncodeURI(sourceMapFile)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
func hookShouldEmitSourceMaps(options *core.CompilerOptions, sourceFile *ast.SourceFile) bool {
|
|
322
|
+
return (options.SourceMap.IsTrue() || options.InlineSourceMap.IsTrue()) &&
|
|
323
|
+
!tspath.FileExtensionIs(sourceFile.FileName(), tspath.ExtensionJson)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
func hookShouldEmitDeclarationSourceMaps(options *core.CompilerOptions, sourceFile *ast.SourceFile) bool {
|
|
327
|
+
return options.DeclarationMap.IsTrue() &&
|
|
328
|
+
!tspath.FileExtensionIs(sourceFile.FileName(), tspath.ExtensionJson)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
func hookSourceRoot(options *core.CompilerOptions) string {
|
|
332
|
+
sourceRoot := tspath.NormalizeSlashes(options.SourceRoot)
|
|
333
|
+
if len(sourceRoot) > 0 {
|
|
334
|
+
sourceRoot = tspath.EnsureTrailingDirectorySeparator(sourceRoot)
|
|
335
|
+
}
|
|
336
|
+
return sourceRoot
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
func hookScriptTransformers(emitContext *printer.EmitContext, host printer.EmitHost, sourceFile *ast.SourceFile) []*transformers.Transformer {
|
|
340
|
+
var tx []*transformers.Transformer
|
|
341
|
+
options := host.Options()
|
|
342
|
+
importElisionEnabled := !options.VerbatimModuleSyntax.IsTrue() && !ast.IsInJSFile(sourceFile.AsNode())
|
|
343
|
+
jsxTransformEnabled := options.GetJSXTransformEnabled() && sourceFile.LanguageVariant == core.LanguageVariantJSX
|
|
344
|
+
emitResolver := host.GetEmitResolver()
|
|
345
|
+
var referenceResolver binder.ReferenceResolver
|
|
346
|
+
if importElisionEnabled || jsxTransformEnabled || !options.GetIsolatedModules() || options.EmitDecoratorMetadata.IsTrue() {
|
|
347
|
+
emitResolver.MarkLinkedReferencesRecursively(sourceFile)
|
|
348
|
+
referenceResolver = emitResolver
|
|
349
|
+
} else {
|
|
350
|
+
referenceResolver = binder.NewReferenceResolver(options, binder.ReferenceResolverHooks{})
|
|
351
|
+
}
|
|
352
|
+
opts := transformers.TransformOptions{
|
|
353
|
+
Context: emitContext,
|
|
354
|
+
CompilerOptions: options,
|
|
355
|
+
Resolver: referenceResolver,
|
|
356
|
+
EmitResolver: emitResolver,
|
|
357
|
+
GetEmitModuleFormatOfFile: host.GetEmitModuleFormatOfFile,
|
|
358
|
+
}
|
|
359
|
+
if options.EmitDecoratorMetadata.IsTrue() {
|
|
360
|
+
tx = append(tx, tstransforms.NewMetadataTransformer(&opts))
|
|
361
|
+
}
|
|
362
|
+
tx = append(tx, tstransforms.NewTypeEraserTransformer(&opts))
|
|
363
|
+
if importElisionEnabled {
|
|
364
|
+
tx = append(tx, tstransforms.NewImportElisionTransformer(&opts))
|
|
365
|
+
}
|
|
366
|
+
tx = append(tx, tstransforms.NewRuntimeSyntaxTransformer(&opts))
|
|
367
|
+
if options.ExperimentalDecorators.IsTrue() {
|
|
368
|
+
tx = append(tx, tstransforms.NewLegacyDecoratorsTransformer(&opts))
|
|
369
|
+
}
|
|
370
|
+
if jsxTransformEnabled {
|
|
371
|
+
tx = append(tx, jsxtransforms.NewJSXTransformer(&opts))
|
|
372
|
+
}
|
|
373
|
+
downleveler := estransforms.GetESTransformer(&opts)
|
|
374
|
+
if downleveler != nil {
|
|
375
|
+
tx = append(tx, downleveler)
|
|
376
|
+
}
|
|
377
|
+
tx = append(tx, estransforms.NewUseStrictTransformer(&opts))
|
|
378
|
+
tx = append(tx, hookModuleTransformer(&opts))
|
|
379
|
+
if !options.GetIsolatedModules() {
|
|
380
|
+
tx = append(tx, inliners.NewConstEnumInliningTransformer(&opts))
|
|
381
|
+
}
|
|
382
|
+
return tx
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
func hookModuleTransformer(opts *transformers.TransformOptions) *transformers.Transformer {
|
|
386
|
+
switch opts.CompilerOptions.GetEmitModuleKind() {
|
|
387
|
+
case core.ModuleKindPreserve:
|
|
388
|
+
return moduletransforms.NewESModuleTransformer(opts)
|
|
389
|
+
case core.ModuleKindESNext,
|
|
390
|
+
core.ModuleKindES2022,
|
|
391
|
+
core.ModuleKindES2020,
|
|
392
|
+
core.ModuleKindES2015,
|
|
393
|
+
core.ModuleKindNode20,
|
|
394
|
+
core.ModuleKindNode18,
|
|
395
|
+
core.ModuleKindNode16,
|
|
396
|
+
core.ModuleKindNodeNext,
|
|
397
|
+
core.ModuleKindCommonJS:
|
|
398
|
+
return moduletransforms.NewImpliedModuleTransformer(opts)
|
|
399
|
+
default:
|
|
400
|
+
return moduletransforms.NewCommonJSModuleTransformer(opts)
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
func (host *hookEmitHost) GetModeForUsageLocation(file ast.HasFileName, moduleSpecifier *ast.StringLiteralLike) core.ResolutionMode {
|
|
405
|
+
return host.program.GetModeForUsageLocation(file, moduleSpecifier)
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
func (host *hookEmitHost) GetResolvedModuleFromModuleSpecifier(file ast.HasFileName, moduleSpecifier *ast.StringLiteralLike) *module.ResolvedModule {
|
|
409
|
+
return host.program.GetResolvedModuleFromModuleSpecifier(file, moduleSpecifier)
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
func (host *hookEmitHost) GetDefaultResolutionModeForFile(file ast.HasFileName) core.ResolutionMode {
|
|
413
|
+
return host.program.GetDefaultResolutionModeForFile(file)
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
func (host *hookEmitHost) GetEmitModuleFormatOfFile(file ast.HasFileName) core.ModuleKind {
|
|
417
|
+
return host.program.GetEmitModuleFormatOfFile(file)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
func (host *hookEmitHost) FileExists(path string) bool {
|
|
421
|
+
return host.program.FileExists(path)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
func (host *hookEmitHost) GetGlobalTypingsCacheLocation() string {
|
|
425
|
+
return host.program.GetGlobalTypingsCacheLocation()
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
func (host *hookEmitHost) GetNearestAncestorDirectoryWithPackageJson(dirname string) string {
|
|
429
|
+
return host.program.GetNearestAncestorDirectoryWithPackageJson(dirname)
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
func (host *hookEmitHost) GetPackageJsonInfo(pkgJSONPath string) *packagejson.InfoCacheEntry {
|
|
433
|
+
return host.program.GetPackageJsonInfo(pkgJSONPath)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
func (host *hookEmitHost) GetSourceOfProjectReferenceIfOutputIncluded(file ast.HasFileName) string {
|
|
437
|
+
return host.program.GetSourceOfProjectReferenceIfOutputIncluded(file)
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
func (host *hookEmitHost) GetProjectReferenceFromSource(path tspath.Path) *tsoptions.SourceOutputAndProjectReference {
|
|
441
|
+
return host.program.GetProjectReferenceFromSource(path)
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
func (host *hookEmitHost) GetRedirectTargets(path tspath.Path) []string {
|
|
445
|
+
return host.program.GetRedirectTargets(path)
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
func (host *hookEmitHost) GetEffectiveDeclarationFlags(node *ast.Node, flags ast.ModifierFlags) ast.ModifierFlags {
|
|
449
|
+
return host.GetEmitResolver().GetEffectiveDeclarationFlags(node, flags)
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
func (host *hookEmitHost) GetOutputPathsFor(file *ast.SourceFile, forceDtsPaths bool) declarations.OutputPaths {
|
|
453
|
+
return outputpaths.GetOutputPathsFor(file, host.Options(), host, forceDtsPaths)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
func (host *hookEmitHost) GetResolutionModeOverride(node *ast.Node) core.ResolutionMode {
|
|
457
|
+
return host.GetEmitResolver().GetResolutionModeOverride(node)
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
func (host *hookEmitHost) GetSourceFileFromReference(origin *ast.SourceFile, ref *ast.FileReference) *ast.SourceFile {
|
|
461
|
+
return host.program.GetSourceFileFromReference(origin, ref)
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
func (host *hookEmitHost) Options() *core.CompilerOptions { return host.program.Options() }
|
|
465
|
+
func (host *hookEmitHost) SourceFiles() []*ast.SourceFile { return host.program.SourceFiles() }
|
|
466
|
+
func (host *hookEmitHost) GetCurrentDirectory() string { return host.program.GetCurrentDirectory() }
|
|
467
|
+
func (host *hookEmitHost) CommonSourceDirectory() string { return host.program.CommonSourceDirectory() }
|
|
468
|
+
func (host *hookEmitHost) UseCaseSensitiveFileNames() bool {
|
|
469
|
+
return host.program.UseCaseSensitiveFileNames()
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
func (host *hookEmitHost) IsEmitBlocked(file string) bool {
|
|
473
|
+
return host.program.IsEmitBlocked(file)
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
func (host *hookEmitHost) WriteFile(fileName string, text string) error {
|
|
477
|
+
return host.program.Host().FS().WriteFile(fileName, text)
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
func (host *hookEmitHost) GetEmitResolver() printer.EmitResolver {
|
|
481
|
+
return host.emitResolver
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
func (host *hookEmitHost) IsSourceFileFromExternalLibrary(file *ast.SourceFile) bool {
|
|
485
|
+
return host.program.IsSourceFileFromExternalLibrary(file)
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
func (host *hookEmitHost) GetSymlinkCache() *symlinks.KnownSymlinks {
|
|
489
|
+
return host.program.GetSymlinkCache()
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
func (host *hookEmitHost) ResolveModuleName(moduleName string, containingFile string, resolutionMode core.ResolutionMode) *module.ResolvedModule {
|
|
493
|
+
return host.program.ResolveModuleName(moduleName, containingFile, resolutionMode)
|
|
494
|
+
}
|
package/shim/core/shim.go
CHANGED
|
@@ -24,3 +24,6 @@ const (
|
|
|
24
24
|
|
|
25
25
|
// NewTextRange constructs a closed/open [pos, end) text range.
|
|
26
26
|
func NewTextRange(pos, end int) TextRange { return innercore.NewTextRange(pos, end) }
|
|
27
|
+
|
|
28
|
+
// UndefinedTextRange marks synthesized AST nodes that do not map to source.
|
|
29
|
+
func UndefinedTextRange() TextRange { return innercore.UndefinedTextRange() }
|
|
@@ -99,9 +99,6 @@ export function runBuild(
|
|
|
99
99
|
const compilers = execution.nativePlugins.filter(
|
|
100
100
|
(plugin) => plugin.stage === "transform",
|
|
101
101
|
);
|
|
102
|
-
const outputs = execution.nativePlugins.filter(
|
|
103
|
-
(plugin) => plugin.stage === "output",
|
|
104
|
-
);
|
|
105
102
|
const checked = runNativeCheckPlugins(options, execution);
|
|
106
103
|
if (checked.status !== 0) {
|
|
107
104
|
return checked;
|
|
@@ -109,7 +106,7 @@ export function runBuild(
|
|
|
109
106
|
|
|
110
107
|
if (options.emit === false) {
|
|
111
108
|
if (compilers.length !== 0) {
|
|
112
|
-
|
|
109
|
+
assertCompilerHostCompatibility(compilers);
|
|
113
110
|
return appendBuildOutput(
|
|
114
111
|
checked,
|
|
115
112
|
buildWithNativeCompilerPlugins(options, execution, compilers),
|
|
@@ -123,7 +120,7 @@ export function runBuild(
|
|
|
123
120
|
|
|
124
121
|
let result: TtscBuildResult;
|
|
125
122
|
if (compilers.length !== 0) {
|
|
126
|
-
|
|
123
|
+
assertCompilerHostCompatibility(compilers);
|
|
127
124
|
result = appendBuildOutput(
|
|
128
125
|
checked,
|
|
129
126
|
buildWithNativeCompilerPlugins(options, execution, compilers),
|
|
@@ -140,25 +137,13 @@ export function runBuild(
|
|
|
140
137
|
}
|
|
141
138
|
}
|
|
142
139
|
const args = createTsgoBuildArgs(execution, options, {
|
|
143
|
-
listEmittedFiles:
|
|
144
|
-
outputs.length !== 0 || options.forceListEmittedFiles === true,
|
|
140
|
+
listEmittedFiles: options.forceListEmittedFiles === true,
|
|
145
141
|
});
|
|
146
142
|
const emitted = runTsgoBuild(execution, options, args);
|
|
147
143
|
result = appendBuildOutput(checked, emitted);
|
|
148
144
|
}
|
|
149
145
|
|
|
150
|
-
|
|
151
|
-
return result;
|
|
152
|
-
}
|
|
153
|
-
return appendBuildOutput(
|
|
154
|
-
result,
|
|
155
|
-
applyOutputPlugins(
|
|
156
|
-
options,
|
|
157
|
-
execution,
|
|
158
|
-
result.emittedFiles ?? [],
|
|
159
|
-
outputs,
|
|
160
|
-
),
|
|
161
|
-
);
|
|
146
|
+
return result;
|
|
162
147
|
}
|
|
163
148
|
|
|
164
149
|
if (options.emit !== false && options.skipDiagnosticsCheck !== true) {
|
|
@@ -332,30 +317,13 @@ function createNativeCheckArgs(
|
|
|
332
317
|
return args;
|
|
333
318
|
}
|
|
334
319
|
|
|
335
|
-
function createNativeOutputArgs(
|
|
336
|
-
execution: ReturnType<typeof resolveExecutionContext>,
|
|
337
|
-
options: TtscBuildOptions,
|
|
338
|
-
file: string,
|
|
339
|
-
): string[] {
|
|
340
|
-
const args = [
|
|
341
|
-
"output",
|
|
342
|
-
"--file=" + file,
|
|
343
|
-
"--tsconfig=" + execution.tsconfig,
|
|
344
|
-
"--plugins-json=" + serializeNativePlugins(execution.nativePlugins),
|
|
345
|
-
"--cwd=" + execution.projectRoot,
|
|
346
|
-
];
|
|
347
|
-
if (options.outDir) {
|
|
348
|
-
args.push("--outDir=" + path.resolve(execution.cwd, options.outDir));
|
|
349
|
-
}
|
|
350
|
-
return args;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
320
|
function serializeNativePlugins(
|
|
354
321
|
plugins: readonly ITtscLoadedNativePlugin[],
|
|
355
322
|
): string {
|
|
356
323
|
return JSON.stringify(
|
|
357
324
|
plugins.map((plugin) => ({
|
|
358
325
|
config: plugin.config,
|
|
326
|
+
hooks: plugin.hooks,
|
|
359
327
|
name: plugin.name,
|
|
360
328
|
stage: plugin.stage,
|
|
361
329
|
})),
|
|
@@ -390,48 +358,6 @@ function runNativeCheckPlugins(
|
|
|
390
358
|
return out;
|
|
391
359
|
}
|
|
392
360
|
|
|
393
|
-
function applyOutputPlugins(
|
|
394
|
-
options: TtscBuildOptions,
|
|
395
|
-
execution: ReturnType<typeof resolveExecutionContext>,
|
|
396
|
-
emittedFiles: readonly string[],
|
|
397
|
-
plugins: readonly ITtscLoadedNativePlugin[],
|
|
398
|
-
): TtscBuildResult {
|
|
399
|
-
let out: TtscBuildResult = {
|
|
400
|
-
diagnostics: [],
|
|
401
|
-
status: 0,
|
|
402
|
-
stdout: "",
|
|
403
|
-
stderr: "",
|
|
404
|
-
};
|
|
405
|
-
for (const plugin of plugins) {
|
|
406
|
-
for (const file of emittedFiles) {
|
|
407
|
-
if (!fs.existsSync(file)) {
|
|
408
|
-
continue;
|
|
409
|
-
}
|
|
410
|
-
const result = runNativeOutputPlugin(options, execution, plugin, file);
|
|
411
|
-
out = appendBuildOutput(out, result);
|
|
412
|
-
if (result.status !== 0) {
|
|
413
|
-
return out;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
return out;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
function runNativeOutputPlugin(
|
|
421
|
-
options: TtscBuildOptions,
|
|
422
|
-
execution: ReturnType<typeof resolveExecutionContext>,
|
|
423
|
-
plugin: ITtscLoadedNativePlugin,
|
|
424
|
-
file: string,
|
|
425
|
-
): TtscBuildResult {
|
|
426
|
-
return runNativePluginCommand(
|
|
427
|
-
plugin,
|
|
428
|
-
createNativeOutputArgs(execution, options, file),
|
|
429
|
-
options,
|
|
430
|
-
execution,
|
|
431
|
-
"ttsc.output",
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
361
|
function runNativePluginCommand(
|
|
436
362
|
plugin: ITtscLoadedNativePlugin,
|
|
437
363
|
args: readonly string[],
|
|
@@ -473,16 +399,59 @@ function appendBuildOutput(
|
|
|
473
399
|
});
|
|
474
400
|
}
|
|
475
401
|
|
|
476
|
-
function
|
|
402
|
+
function assertCompilerHostCompatibility(
|
|
477
403
|
plugins: readonly ITtscLoadedNativePlugin[],
|
|
478
404
|
): void {
|
|
479
405
|
const binaries = [...new Set(plugins.map((plugin) => plugin.binary))];
|
|
480
|
-
if (binaries.length
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
406
|
+
if (binaries.length <= 1) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (plugins.every(isFirstPartyUtilityTransformPlugin)) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
throw new Error(
|
|
413
|
+
"ttsc: multiple compiler native backends cannot share one emit pass; " +
|
|
414
|
+
"compose transform hook libraries through one aggregate host",
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function isFirstPartyUtilityTransformPlugin(
|
|
419
|
+
plugin: ITtscLoadedNativePlugin,
|
|
420
|
+
): boolean {
|
|
421
|
+
if (plugin.stage !== "transform") return false;
|
|
422
|
+
if (!firstPartyUtilityPluginNames.has(plugin.name)) return false;
|
|
423
|
+
const manifest = readNearestPackageManifest(plugin.source);
|
|
424
|
+
return manifest?.name === plugin.name;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const firstPartyUtilityPluginNames = new Set([
|
|
428
|
+
"@ttsc/banner",
|
|
429
|
+
"@ttsc/paths",
|
|
430
|
+
"@ttsc/strip",
|
|
431
|
+
]);
|
|
432
|
+
|
|
433
|
+
function readNearestPackageManifest(
|
|
434
|
+
source: string,
|
|
435
|
+
): { name?: unknown } | undefined {
|
|
436
|
+
try {
|
|
437
|
+
let current = fs.statSync(source).isDirectory()
|
|
438
|
+
? source
|
|
439
|
+
: path.dirname(source);
|
|
440
|
+
for (let i = 0; i < 4; i += 1) {
|
|
441
|
+
const manifest = path.join(current, "package.json");
|
|
442
|
+
if (fs.existsSync(manifest)) {
|
|
443
|
+
return JSON.parse(fs.readFileSync(manifest, "utf8")) as {
|
|
444
|
+
name?: unknown;
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
const parent = path.dirname(current);
|
|
448
|
+
if (parent === current) break;
|
|
449
|
+
current = parent;
|
|
450
|
+
}
|
|
451
|
+
} catch {
|
|
452
|
+
return undefined;
|
|
485
453
|
}
|
|
454
|
+
return undefined;
|
|
486
455
|
}
|
|
487
456
|
|
|
488
457
|
function resolveExecutionContext(
|