Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 71 additions & 2 deletions dist/transpiler.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6196,7 +6196,8 @@ var JavaTranspiler = class extends BaseTranspiler {
}
printThrowStatement(node, identation) {
if (node.expression.kind === _typescript2.default.SyntaxKind.Identifier) {
return this.getIden(identation) + this.THROW_TOKEN + " " + this.printNode(node.expression, 0) + this.LINE_TERMINATOR;
const name = this.printNode(node.expression, 0);
return this.getIden(identation) + `${this.THROW_TOKEN} (${name} instanceof RuntimeException ? (RuntimeException)${name} : new RuntimeException(${name}))${this.LINE_TERMINATOR}`;
}
if (node.expression.kind === _typescript2.default.SyntaxKind.NewExpression) {
const expression = node.expression;
Expand Down Expand Up @@ -7342,6 +7343,29 @@ var Transpiler = class _Transpiler {
program
});
}
// One program over N root files, instead of one program per file. Every
// transpile*ByPath call pays for a full program: even with the SourceFile cache
// making the ~340-file import closure parse-free, the binder/checker work behind
// getPreEmitDiagnostics is redone per file. Batching N files into one program
// pays it once for the whole set.
//
// Files that import each other (a derived exchange and its parent) are fine in
// one batch — they are separate root files of the same program, exactly as
// typescript would compile a project.
//
// The batch deliberately does not become the cache's byPathOldProgram: an N-file
// program never structurally reuses a program built from a different root set, so
// there is nothing to gain, and keeping the previous chunk's checker alive while
// the next one is built would double peak memory — the opposite of why callers
// chunk. The cross-batch saving comes from the shared host + SourceFile cache.
createProgramBatch(paths) {
const options = fastCompilerOptions;
const host = this.getByPathCompilerHost(options);
const program = _typescript2.default.createProgram([...paths, globalsShimPath], options, host);
const checker = program.getTypeChecker();
memoizeCheckerCalls(checker);
return new TranspileProgramBatch(this, program, checker);
}
// the language printers read the typescript state (source file, checker, program)
// off the context handed to them here, so two Transpiler instances never share
// state and a nested transpile can restore whatever its caller was working on
Expand Down Expand Up @@ -7548,8 +7572,53 @@ var Transpiler = class _Transpiler {
}
}
};
var TranspileProgramBatch = class {
constructor(transpiler, program, checker) {
this.transpiler = transpiler;
this.program = program;
this.checker = checker;
}
getProgram() {
return this.program;
}
// point the owning Transpiler at one file of this batch, then run the same
// diagnostics pass the single-file path runs — the printers read checker state
// back from it, so it is not optional
setContextForPath(filePath) {
const src = _nullishCoalesce(this.program.getSourceFile(filePath), () => ( this.program.getSourceFile(path.resolve(filePath))));
if (src === void 0) {
throw new Error(`ast-transpiler: "${filePath}" is not a file of this program batch`);
}
const context = this.transpiler.setContext({ src, checker: this.checker, program: this.program });
this.transpiler.checkFileDiagnostics(context);
return context;
}
transpileByPath(lang, filePath, sync = false) {
this.setContextForPath(filePath);
return this.transpiler.transpile(lang, 0 /* ByPath */, filePath, sync, false);
}
transpilePythonByPath(filePath) {
return this.transpileByPath(0 /* Python */, filePath, !this.transpiler.pythonTranspiler.asyncTranspiling);
}
transpilePhpByPath(filePath) {
return this.transpileByPath(1 /* Php */, filePath, !this.transpiler.phpTranspiler.asyncTranspiling);
}
transpileCSharpByPath(filePath) {
return this.transpileByPath(2 /* CSharp */, filePath);
}
transpileGoByPath(filePath) {
return this.transpileByPath(3 /* Go */, filePath);
}
transpileJavaByPath(filePath) {
return this.transpileByPath(4 /* Java */, filePath);
}
transpileRustByPath(filePath) {
return this.transpileByPath(5 /* Rust */, filePath);
}
};




exports.Transpiler = Transpiler; exports.default = Transpiler;
exports.TranspileProgramBatch = TranspileProgramBatch; exports.Transpiler = Transpiler; exports.default = Transpiler;
//# sourceMappingURL=transpiler.cjs.map
2 changes: 1 addition & 1 deletion dist/transpiler.cjs.map

Large diffs are not rendered by default.

18 changes: 17 additions & 1 deletion dist/transpiler.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,7 @@ declare class Transpiler {
createProgramInMemoryAndSetContext(content: any): ITranspileContext;
getByPathCompilerHost(options: ts.CompilerOptions): ts.CompilerHost;
createProgramByPathAndSetContext(path: any): ITranspileContext;
createProgramBatch(paths: string[]): TranspileProgramBatch;
setContext(context: ITranspileContext): ITranspileContext;
/** @deprecated renamed to createProgramInMemoryAndSetContext */
createProgramInMemoryAndSetGlobals(content: any): ITranspileContext;
Expand Down Expand Up @@ -928,5 +929,20 @@ declare class Transpiler {
setPythonStringLiteralReplacements(replacements: any): void;
convertStringToLanguageEnum(lang: string): Languages;
}
declare class TranspileProgramBatch {
private readonly transpiler;
private readonly program;
private readonly checker;
constructor(transpiler: Transpiler, program: ts.Program, checker: ts.TypeChecker);
getProgram(): ts.Program;
setContextForPath(filePath: string): ITranspileContext;
transpileByPath(lang: Languages, filePath: string, sync?: boolean): ITranspiledFile;
transpilePythonByPath(filePath: string): ITranspiledFile;
transpilePhpByPath(filePath: string): ITranspiledFile;
transpileCSharpByPath(filePath: string): ITranspiledFile;
transpileGoByPath(filePath: string): ITranspiledFile;
transpileJavaByPath(filePath: string): ITranspiledFile;
transpileRustByPath(filePath: string): ITranspiledFile;
}

export { Transpiler, Transpiler as default };
export { TranspileProgramBatch, Transpiler, Transpiler as default };
71 changes: 70 additions & 1 deletion dist/transpiler.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/transpiler.js.map

Large diffs are not rendered by default.

98 changes: 97 additions & 1 deletion src/transpiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,30 @@ export default class Transpiler {
});
}

// One program over N root files, instead of one program per file. Every
// transpile*ByPath call pays for a full program: even with the SourceFile cache
// making the ~340-file import closure parse-free, the binder/checker work behind
// getPreEmitDiagnostics is redone per file. Batching N files into one program
// pays it once for the whole set.
//
// Files that import each other (a derived exchange and its parent) are fine in
// one batch — they are separate root files of the same program, exactly as
// typescript would compile a project.
//
// The batch deliberately does not become the cache's byPathOldProgram: an N-file
// program never structurally reuses a program built from a different root set, so
// there is nothing to gain, and keeping the previous chunk's checker alive while
// the next one is built would double peak memory — the opposite of why callers
// chunk. The cross-batch saving comes from the shared host + SourceFile cache.
createProgramBatch(paths: string[]): TranspileProgramBatch {
const options: ts.CompilerOptions = fastCompilerOptions;
const host = this.getByPathCompilerHost(options);
const program = ts.createProgram([...paths, globalsShimPath], options, host);
const checker = program.getTypeChecker();
memoizeCheckerCalls(checker);
return new TranspileProgramBatch(this, program, checker);
}

// the language printers read the typescript state (source file, checker, program)
// off the context handed to them here, so two Transpiler instances never share
// state and a nested transpile can restore whatever its caller was working on
Expand Down Expand Up @@ -536,6 +560,78 @@ export default class Transpiler {
}
}

// A set of root files compiled as one typescript program, transpiled one at a time.
// Obtained from Transpiler.createProgramBatch; mirrors the transpile*ByPath methods
// of the Transpiler it came from, so a caller batches by replacing
// for (const f of files) transpiler.transpileGoByPath(f)
// with
// const batch = transpiler.createProgramBatch(files);
// for (const f of files) batch.transpileGoByPath(f)
//
// A failing file throws out of its own call and leaves the batch usable: the context
// is rebuilt from the program on every call, so the caller can try/catch per file and
// keep going. The batch borrows the Transpiler's printers and context, so do not
// drive that Transpiler through another path while a batch loop is in flight — use
// cloneSharingProgramCache() for a second, independent driver.
class TranspileProgramBatch {
private readonly transpiler: Transpiler;
private readonly program: ts.Program;
private readonly checker: ts.TypeChecker;

constructor(transpiler: Transpiler, program: ts.Program, checker: ts.TypeChecker) {
this.transpiler = transpiler;
this.program = program;
this.checker = checker;
}

getProgram(): ts.Program {
return this.program;
}

// point the owning Transpiler at one file of this batch, then run the same
// diagnostics pass the single-file path runs — the printers read checker state
// back from it, so it is not optional
setContextForPath(filePath: string): ITranspileContext {
const src = this.program.getSourceFile(filePath) ?? this.program.getSourceFile(path.resolve(filePath));
if (src === undefined) {
throw new Error(`ast-transpiler: "${filePath}" is not a file of this program batch`);
}
const context = this.transpiler.setContext({ src, checker: this.checker, program: this.program });
this.transpiler.checkFileDiagnostics(context);
return context;
}

transpileByPath(lang: Languages, filePath: string, sync = false): ITranspiledFile {
this.setContextForPath(filePath);
return this.transpiler.transpile(lang, TranspilationMode.ByPath, filePath, sync, false);
}

transpilePythonByPath(filePath: string): ITranspiledFile {
return this.transpileByPath(Languages.Python, filePath, !this.transpiler.pythonTranspiler.asyncTranspiling);
}

transpilePhpByPath(filePath: string): ITranspiledFile {
return this.transpileByPath(Languages.Php, filePath, !this.transpiler.phpTranspiler.asyncTranspiling);
}

transpileCSharpByPath(filePath: string): ITranspiledFile {
return this.transpileByPath(Languages.CSharp, filePath);
}

transpileGoByPath(filePath: string): ITranspiledFile {
return this.transpileByPath(Languages.Go, filePath);
}

transpileJavaByPath(filePath: string): ITranspiledFile {
return this.transpileByPath(Languages.Java, filePath);
}

transpileRustByPath(filePath: string): ITranspiledFile {
return this.transpileByPath(Languages.Rust, filePath);
}
}

export {
Transpiler
Transpiler,
TranspileProgramBatch
};
Loading
Loading