jsii-rosetta 5.9.16-dev.3 → 5.9.19
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 +14 -0
- package/lib/commands/extract.d.ts +6 -0
- package/lib/commands/extract.js +16 -3
- package/lib/commands/extract.js.map +1 -1
- package/lib/commands/infuse.js +1 -1
- package/lib/commands/infuse.js.map +1 -1
- package/lib/commands/transliterate.d.ts +6 -0
- package/lib/commands/transliterate.js +1 -0
- package/lib/commands/transliterate.js.map +1 -1
- package/lib/languages/python.js +16 -7
- package/lib/languages/python.js.map +1 -1
- package/lib/logging.d.ts +3 -3
- package/lib/logging.js +14 -6
- package/lib/logging.js.map +1 -1
- package/lib/main.js +15 -0
- package/lib/main.js.map +1 -1
- package/lib/o-tree.d.ts +20 -6
- package/lib/o-tree.js +45 -4
- package/lib/o-tree.js.map +1 -1
- package/lib/renderer.d.ts +1 -1
- package/lib/renderer.js +1 -1
- package/lib/renderer.js.map +1 -1
- package/lib/rosetta-reader.js +2 -2
- package/lib/rosetta-reader.js.map +1 -1
- package/lib/rosetta-translator.d.ts +6 -0
- package/lib/rosetta-translator.js +3 -5
- package/lib/rosetta-translator.js.map +1 -1
- package/lib/translate.d.ts +73 -27
- package/lib/translate.js +142 -56
- package/lib/translate.js.map +1 -1
- package/lib/translate_all.d.ts +1 -1
- package/lib/translate_all.js +12 -4
- package/lib/translate_all.js.map +1 -1
- package/lib/translate_all_worker.d.ts +4 -0
- package/lib/translate_all_worker.js +22 -1
- package/lib/translate_all_worker.js.map +1 -1
- package/lib/typescript/ts-compiler.d.ts +9 -2
- package/lib/typescript/ts-compiler.js +42 -25
- package/lib/typescript/ts-compiler.js.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rosetta-translator.js","sourceRoot":"","sources":["../src/rosetta-translator.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport * as spec from '@jsii/spec';\n\nimport { TypeFingerprinter } from './jsii/fingerprinting';\nimport { TARGET_LANGUAGES } from './languages';\nimport * as logging from './logging';\nimport { TypeScriptSnippet, completeSource } from './snippet';\nimport {\n collectDependencies,\n validateAvailableDependencies,\n prepareDependencyDirectory,\n expandWithTransitiveDependencies,\n} from './snippet-dependencies';\nimport { snippetKey } from './tablets/key';\nimport { LanguageTablet, TranslatedSnippet } from './tablets/tablets';\nimport { translateAll, TranslateAllResult } from './translate_all';\n\nexport interface RosettaTranslatorOptions {\n /**\n * Assemblies to use for fingerprinting\n *\n * The set of assemblies here are used to invalidate the cache. Any types that are\n * used in snippets are looked up in this set of assemblies. If found, their type\n * information is fingerprinted and compared to the type information at the time\n * compilation of the cached sample. If different, this is considered to be a cache\n * miss.\n *\n * You must use the same set of assemblies when generating and reading the cache\n * file, otherwise the fingerprint is guaranteed to be different and the cache will\n * be useless (e.g. if you generate the cache WITH assembly information but\n * read it without, or vice versa).\n *\n * @default No assemblies.\n */\n readonly assemblies?: spec.Assembly[];\n\n /**\n * Whether to include compiler diagnostics in the compilation results.\n *\n * @default false\n */\n readonly includeCompilerDiagnostics?: boolean;\n\n /**\n * Allow reading dirty translations from cache\n *\n * @default false\n */\n readonly allowDirtyTranslations?: boolean;\n}\n\n/**\n * Entry point for consumers that want to translate code on-the-fly\n *\n * If you want to generate and translate code on-the-fly, in ways that cannot\n * be achieved by the rosetta CLI, use this class.\n */\nexport class RosettaTranslator {\n /**\n * Tablet with fresh translations\n *\n * All new translations (not read from cache) are added to this tablet.\n */\n public readonly tablet = new LanguageTablet();\n\n public readonly cache = new LanguageTablet();\n\n private readonly fingerprinter: TypeFingerprinter;\n private readonly includeCompilerDiagnostics: boolean;\n private readonly allowDirtyTranslations: boolean;\n\n public constructor(options: RosettaTranslatorOptions = {}) {\n this.fingerprinter = new TypeFingerprinter(options?.assemblies ?? []);\n this.includeCompilerDiagnostics = options.includeCompilerDiagnostics ?? false;\n this.allowDirtyTranslations = options.allowDirtyTranslations ?? false;\n }\n\n /**\n * @deprecated use `addToCache` instead\n */\n public async loadCache(fileName: string) {\n try {\n await this.cache.load(fileName);\n } catch (e: any) {\n logging.warn(`Error reading cache ${fileName}: ${e.message}`);\n }\n }\n\n public async addToCache(filename: string) {\n const tab = await LanguageTablet.fromOptionalFile(filename);\n this.cache.addTablet(tab);\n }\n\n public addTabletsToCache(...tablets: LanguageTablet[]) {\n for (const tab of tablets) {\n this.cache.addTablet(tab);\n }\n }\n\n public hasCache() {\n return this.cache.count > 0;\n }\n\n /**\n * For all the given snippets, try to read translations from the cache\n *\n * Will remove the cached snippets from the input array.\n */\n public readFromCache(snippets: TypeScriptSnippet[], addToTablet = true, compiledOnly = false): ReadFromCacheResults {\n const translations = new Array<TranslatedSnippet>();\n const remaining = new Array<TypeScriptSnippet>();\n\n let infusedCount = 0;\n let dirtyCount = 0;\n let dirtySourceCount = 0;\n let dirtyTypesCount = 0;\n let dirtyTranslatorCount = 0;\n let dirtyDidntCompile = 0;\n\n for (const snippet of snippets) {\n const fromCache = tryReadFromCache(snippet, this.cache, this.fingerprinter, compiledOnly);\n switch (fromCache.type) {\n case 'hit':\n if (addToTablet) {\n this.tablet.addSnippet(fromCache.snippet);\n }\n translations.push(fromCache.snippet);\n\n infusedCount += fromCache.infused ? 1 : 0;\n break;\n\n case 'dirty':\n dirtyCount += 1;\n dirtySourceCount += fromCache.dirtySource ? 1 : 0;\n dirtyTranslatorCount += fromCache.dirtyTranslator ? 1 : 0;\n dirtyTypesCount += fromCache.dirtyTypes ? 1 : 0;\n dirtyDidntCompile += fromCache.dirtyDidntCompile ? 1 : 0;\n\n if (this.allowDirtyTranslations) {\n translations.push(fromCache.translation);\n } else {\n remaining.push(snippet);\n }\n break;\n\n case 'miss':\n remaining.push(snippet);\n break;\n }\n }\n\n return {\n translations,\n remaining,\n infusedCount,\n dirtyCount,\n dirtySourceCount,\n dirtyTranslatorCount,\n dirtyTypesCount,\n dirtyDidntCompile,\n };\n }\n\n public async translateAll(snippets: TypeScriptSnippet[], addToTablet?: boolean): Promise<TranslateAllResult>;\n public async translateAll(snippets: TypeScriptSnippet[], options?: TranslateAllOptions): Promise<TranslateAllResult>;\n public async translateAll(\n snippets: TypeScriptSnippet[],\n optionsOrAddToTablet?: boolean | TranslateAllOptions,\n ): Promise<TranslateAllResult> {\n const options =\n optionsOrAddToTablet && typeof optionsOrAddToTablet === 'object'\n ? optionsOrAddToTablet\n : { addToTablet: optionsOrAddToTablet };\n\n const exampleDependencies = collectDependencies(snippets);\n await expandWithTransitiveDependencies(exampleDependencies);\n\n let compilationDirectory;\n let cleanCompilationDir = false;\n if (options?.compilationDirectory) {\n // If the user provided a directory, we're going to trust-but-confirm.\n await validateAvailableDependencies(options.compilationDirectory, exampleDependencies);\n compilationDirectory = options.compilationDirectory;\n } else {\n compilationDirectory = await prepareDependencyDirectory(exampleDependencies);\n cleanCompilationDir = true;\n }\n\n const origDir = process.cwd();\n // Easiest way to get a fixed working directory (for sources) in is to chdir\n process.chdir(compilationDirectory);\n\n let result;\n try {\n result = await translateAll(snippets, this.includeCompilerDiagnostics);\n } finally {\n process.chdir(origDir);\n if (cleanCompilationDir) {\n if (options.cleanup ?? true) {\n await fs.rm(compilationDirectory, { force: true, recursive: true });\n } else {\n logging.info(`Leaving directory uncleaned: ${compilationDirectory}`);\n }\n }\n }\n\n const fingerprinted = result.translatedSnippets.map((snippet) =>\n snippet.withFingerprint(this.fingerprinter.fingerprintAll(snippet.fqnsReferenced())),\n );\n\n if (options?.addToTablet ?? true) {\n for (const translation of fingerprinted) {\n this.tablet.addSnippet(translation);\n }\n }\n\n return {\n translatedSnippets: fingerprinted,\n diagnostics: result.diagnostics,\n };\n }\n}\n\n/**\n * Try to find the translation for the given snippet in the given cache\n *\n * Rules for cacheability are:\n * - id is the same (== visible source didn't change)\n * - complete source is the same (== fixture didn't change)\n * - all types involved have the same fingerprint (== API surface didn't change)\n * - the versions of all translations match the versions on the available translators (== translator itself didn't change)\n *\n * For the versions check: we could have selectively picked some translations\n * from the cache while performing others. However, since the big work is in\n * parsing the TypeScript, and the rendering itself is peanutes (assumption), it\n * doesn't really make a lot of difference. So, for simplification's sake,\n * we'll regen all translations if there's at least one that's outdated.\n */\nfunction tryReadFromCache(\n sourceSnippet: TypeScriptSnippet,\n cache: LanguageTablet,\n fingerprinter: TypeFingerprinter,\n compiledOnly: boolean,\n): CacheHit {\n const fromCache = cache.tryGetSnippet(snippetKey(sourceSnippet));\n\n if (!fromCache) {\n return { type: 'miss' };\n }\n\n // infused snippets won't pass the full source check or the fingerprinter\n // but there is no reason to try to recompile it, so return cached snippet\n // if there exists one.\n if (isInfused(sourceSnippet)) {\n return { type: 'hit', snippet: fromCache, infused: true };\n }\n\n const dirtySource = completeSource(sourceSnippet) !== fromCache.snippet.fullSource;\n const dirtyTranslator = !Object.entries(TARGET_LANGUAGES).every(\n ([lang, translator]) => fromCache.snippet.translations?.[lang]?.version === translator.version,\n );\n const dirtyTypes = fingerprinter.fingerprintAll(fromCache.fqnsReferenced()) !== fromCache.snippet.fqnsFingerprint;\n const dirtyDidntCompile = compiledOnly && !fromCache.snippet.didCompile;\n\n if (dirtySource || dirtyTranslator || dirtyTypes || dirtyDidntCompile) {\n return { type: 'dirty', translation: fromCache, dirtySource, dirtyTranslator, dirtyTypes, dirtyDidntCompile };\n }\n return { type: 'hit', snippet: fromCache, infused: false };\n}\n\nexport type CacheHit =\n | { readonly type: 'miss' }\n | { readonly type: 'hit'; readonly snippet: TranslatedSnippet; readonly infused: boolean }\n | {\n readonly type: 'dirty';\n readonly translation: TranslatedSnippet;\n readonly dirtySource: boolean;\n readonly dirtyTranslator: boolean;\n readonly dirtyTypes: boolean;\n readonly dirtyDidntCompile: boolean;\n };\n\nfunction isInfused(snippet: TypeScriptSnippet) {\n return snippet.parameters?.infused !== undefined;\n}\n\nexport interface ReadFromCacheResults {\n /**\n * Successful translations\n */\n readonly translations: TranslatedSnippet[];\n\n /**\n * Successful but dirty hits\n */\n readonly remaining: TypeScriptSnippet[];\n\n /**\n * How many successfully hit translations were infused\n */\n readonly infusedCount: number;\n\n readonly dirtyCount: number;\n\n // Counts for dirtiness (a single snippet may be dirty for more than one reason)\n readonly dirtySourceCount: number;\n readonly dirtyTranslatorCount: number;\n readonly dirtyTypesCount: number;\n readonly dirtyDidntCompile: number;\n}\n\nexport interface TranslateAllOptions {\n /**\n * @default - Create a temporary directory with all necessary packages\n */\n readonly compilationDirectory?: string;\n\n /**\n * @default true\n */\n readonly addToTablet?: boolean;\n\n /**\n * @default true\n */\n readonly cleanup?: boolean;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"rosetta-translator.js","sourceRoot":"","sources":["../src/rosetta-translator.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport * as spec from '@jsii/spec';\n\nimport { TypeFingerprinter } from './jsii/fingerprinting';\nimport { TARGET_LANGUAGES } from './languages';\nimport * as logging from './logging';\nimport { TypeScriptSnippet, completeSource } from './snippet';\nimport {\n collectDependencies,\n validateAvailableDependencies,\n prepareDependencyDirectory,\n expandWithTransitiveDependencies,\n} from './snippet-dependencies';\nimport { snippetKey } from './tablets/key';\nimport { LanguageTablet, TranslatedSnippet } from './tablets/tablets';\nimport { translateAll, TranslateAllResult } from './translate_all';\n\nexport interface RosettaTranslatorOptions {\n /**\n * Assemblies to use for fingerprinting\n *\n * The set of assemblies here are used to invalidate the cache. Any types that are\n * used in snippets are looked up in this set of assemblies. If found, their type\n * information is fingerprinted and compared to the type information at the time\n * compilation of the cached sample. If different, this is considered to be a cache\n * miss.\n *\n * You must use the same set of assemblies when generating and reading the cache\n * file, otherwise the fingerprint is guaranteed to be different and the cache will\n * be useless (e.g. if you generate the cache WITH assembly information but\n * read it without, or vice versa).\n *\n * @default No assemblies.\n */\n readonly assemblies?: spec.Assembly[];\n\n /**\n * Whether to include compiler diagnostics in the compilation results.\n *\n * @default false\n */\n readonly includeCompilerDiagnostics?: boolean;\n\n /**\n * Allow reading dirty translations from cache\n *\n * @default false\n */\n readonly allowDirtyTranslations?: boolean;\n}\n\n/**\n * Entry point for consumers that want to translate code on-the-fly\n *\n * If you want to generate and translate code on-the-fly, in ways that cannot\n * be achieved by the rosetta CLI, use this class.\n */\nexport class RosettaTranslator {\n /**\n * Tablet with fresh translations\n *\n * All new translations (not read from cache) are added to this tablet.\n */\n public readonly tablet = new LanguageTablet();\n\n public readonly cache = new LanguageTablet();\n\n private readonly fingerprinter: TypeFingerprinter;\n private readonly includeCompilerDiagnostics: boolean;\n private readonly allowDirtyTranslations: boolean;\n\n public constructor(options: RosettaTranslatorOptions = {}) {\n this.fingerprinter = new TypeFingerprinter(options?.assemblies ?? []);\n this.includeCompilerDiagnostics = options.includeCompilerDiagnostics ?? false;\n this.allowDirtyTranslations = options.allowDirtyTranslations ?? false;\n }\n\n /**\n * @deprecated use `addToCache` instead\n */\n public async loadCache(fileName: string) {\n try {\n await this.cache.load(fileName);\n } catch (e: any) {\n logging.warn(`Error reading cache ${fileName}: ${e.message}`);\n }\n }\n\n public async addToCache(filename: string) {\n const tab = await LanguageTablet.fromOptionalFile(filename);\n this.cache.addTablet(tab);\n }\n\n public addTabletsToCache(...tablets: LanguageTablet[]) {\n for (const tab of tablets) {\n this.cache.addTablet(tab);\n }\n }\n\n public hasCache() {\n return this.cache.count > 0;\n }\n\n /**\n * For all the given snippets, try to read translations from the cache\n *\n * Will remove the cached snippets from the input array.\n */\n public readFromCache(snippets: TypeScriptSnippet[], addToTablet = true, compiledOnly = false): ReadFromCacheResults {\n const translations = new Array<TranslatedSnippet>();\n const remaining = new Array<TypeScriptSnippet>();\n\n let infusedCount = 0;\n let dirtyCount = 0;\n let dirtySourceCount = 0;\n let dirtyTypesCount = 0;\n let dirtyTranslatorCount = 0;\n let dirtyDidntCompile = 0;\n\n for (const snippet of snippets) {\n const fromCache = tryReadFromCache(snippet, this.cache, this.fingerprinter, compiledOnly);\n switch (fromCache.type) {\n case 'hit':\n if (addToTablet) {\n this.tablet.addSnippets(fromCache.snippet);\n }\n translations.push(fromCache.snippet);\n\n infusedCount += fromCache.infused ? 1 : 0;\n break;\n\n case 'dirty':\n dirtyCount += 1;\n dirtySourceCount += fromCache.dirtySource ? 1 : 0;\n dirtyTranslatorCount += fromCache.dirtyTranslator ? 1 : 0;\n dirtyTypesCount += fromCache.dirtyTypes ? 1 : 0;\n dirtyDidntCompile += fromCache.dirtyDidntCompile ? 1 : 0;\n\n if (this.allowDirtyTranslations) {\n translations.push(fromCache.translation);\n } else {\n remaining.push(snippet);\n }\n break;\n\n case 'miss':\n remaining.push(snippet);\n break;\n }\n }\n\n return {\n translations,\n remaining,\n infusedCount,\n dirtyCount,\n dirtySourceCount,\n dirtyTranslatorCount,\n dirtyTypesCount,\n dirtyDidntCompile,\n };\n }\n\n public async translateAll(snippets: TypeScriptSnippet[], addToTablet?: boolean): Promise<TranslateAllResult>;\n public async translateAll(snippets: TypeScriptSnippet[], options?: TranslateAllOptions): Promise<TranslateAllResult>;\n public async translateAll(\n snippets: TypeScriptSnippet[],\n optionsOrAddToTablet?: boolean | TranslateAllOptions,\n ): Promise<TranslateAllResult> {\n const options =\n optionsOrAddToTablet && typeof optionsOrAddToTablet === 'object'\n ? optionsOrAddToTablet\n : { addToTablet: optionsOrAddToTablet };\n\n const exampleDependencies = collectDependencies(snippets);\n await expandWithTransitiveDependencies(exampleDependencies);\n\n let compilationDirectory;\n let cleanCompilationDir = false;\n if (options?.compilationDirectory) {\n // If the user provided a directory, we're going to trust-but-confirm.\n await validateAvailableDependencies(options.compilationDirectory, exampleDependencies);\n compilationDirectory = options.compilationDirectory;\n } else {\n compilationDirectory = await prepareDependencyDirectory(exampleDependencies);\n cleanCompilationDir = true;\n }\n\n const origDir = process.cwd();\n // Easiest way to get a fixed working directory (for sources) in is to chdir\n process.chdir(compilationDirectory);\n\n let result;\n try {\n result = await translateAll(snippets, this.includeCompilerDiagnostics, options?.batchSize);\n } finally {\n process.chdir(origDir);\n if (cleanCompilationDir) {\n if (options.cleanup ?? true) {\n await fs.rm(compilationDirectory, { force: true, recursive: true });\n } else {\n logging.info(`Leaving directory uncleaned: ${compilationDirectory}`);\n }\n }\n }\n\n const fingerprinted = result.translatedSnippets.map((snippet) =>\n snippet.withFingerprint(this.fingerprinter.fingerprintAll(snippet.fqnsReferenced())),\n );\n\n if (options?.addToTablet ?? true) {\n this.tablet.addSnippets(...fingerprinted);\n }\n\n return {\n translatedSnippets: fingerprinted,\n diagnostics: result.diagnostics,\n };\n }\n}\n\n/**\n * Try to find the translation for the given snippet in the given cache\n *\n * Rules for cacheability are:\n * - id is the same (== visible source didn't change)\n * - complete source is the same (== fixture didn't change)\n * - all types involved have the same fingerprint (== API surface didn't change)\n * - the versions of all translations match the versions on the available translators (== translator itself didn't change)\n *\n * For the versions check: we could have selectively picked some translations\n * from the cache while performing others. However, since the big work is in\n * parsing the TypeScript, and the rendering itself is peanutes (assumption), it\n * doesn't really make a lot of difference. So, for simplification's sake,\n * we'll regen all translations if there's at least one that's outdated.\n */\nfunction tryReadFromCache(\n sourceSnippet: TypeScriptSnippet,\n cache: LanguageTablet,\n fingerprinter: TypeFingerprinter,\n compiledOnly: boolean,\n): CacheHit {\n const fromCache = cache.tryGetSnippet(snippetKey(sourceSnippet));\n\n if (!fromCache) {\n return { type: 'miss' };\n }\n\n // infused snippets won't pass the full source check or the fingerprinter\n // but there is no reason to try to recompile it, so return cached snippet\n // if there exists one.\n if (isInfused(sourceSnippet)) {\n return { type: 'hit', snippet: fromCache, infused: true };\n }\n\n const dirtySource = completeSource(sourceSnippet) !== fromCache.snippet.fullSource;\n const dirtyTranslator = !Object.entries(TARGET_LANGUAGES).every(\n ([lang, translator]) => fromCache.snippet.translations?.[lang]?.version === translator.version,\n );\n const dirtyTypes = fingerprinter.fingerprintAll(fromCache.fqnsReferenced()) !== fromCache.snippet.fqnsFingerprint;\n const dirtyDidntCompile = compiledOnly && !fromCache.snippet.didCompile;\n\n if (dirtySource || dirtyTranslator || dirtyTypes || dirtyDidntCompile) {\n return { type: 'dirty', translation: fromCache, dirtySource, dirtyTranslator, dirtyTypes, dirtyDidntCompile };\n }\n return { type: 'hit', snippet: fromCache, infused: false };\n}\n\nexport type CacheHit =\n | { readonly type: 'miss' }\n | { readonly type: 'hit'; readonly snippet: TranslatedSnippet; readonly infused: boolean }\n | {\n readonly type: 'dirty';\n readonly translation: TranslatedSnippet;\n readonly dirtySource: boolean;\n readonly dirtyTranslator: boolean;\n readonly dirtyTypes: boolean;\n readonly dirtyDidntCompile: boolean;\n };\n\nfunction isInfused(snippet: TypeScriptSnippet) {\n return snippet.parameters?.infused !== undefined;\n}\n\nexport interface ReadFromCacheResults {\n /**\n * Successful translations\n */\n readonly translations: TranslatedSnippet[];\n\n /**\n * Successful but dirty hits\n */\n readonly remaining: TypeScriptSnippet[];\n\n /**\n * How many successfully hit translations were infused\n */\n readonly infusedCount: number;\n\n readonly dirtyCount: number;\n\n // Counts for dirtiness (a single snippet may be dirty for more than one reason)\n readonly dirtySourceCount: number;\n readonly dirtyTranslatorCount: number;\n readonly dirtyTypesCount: number;\n readonly dirtyDidntCompile: number;\n}\n\nexport interface TranslateAllOptions {\n /**\n * @default - Create a temporary directory with all necessary packages\n */\n readonly compilationDirectory?: string;\n\n /**\n * @default true\n */\n readonly addToTablet?: boolean;\n\n /**\n * @default true\n */\n readonly cleanup?: boolean;\n\n /**\n * Batch size for compiling snippets together\n *\n * @default undefined (no batching)\n */\n readonly batchSize?: number;\n}\n"]}
|
package/lib/translate.d.ts
CHANGED
|
@@ -3,8 +3,12 @@ import { TargetLanguage } from './languages';
|
|
|
3
3
|
import { AstHandler, AstRendererOptions } from './renderer';
|
|
4
4
|
import { TypeScriptSnippet } from './snippet';
|
|
5
5
|
import { TranslatedSnippet } from './tablets/tablets';
|
|
6
|
-
import { TypeScriptCompiler } from './typescript/ts-compiler';
|
|
6
|
+
import { TypeScriptCompiler, CompilationResult } from './typescript/ts-compiler';
|
|
7
7
|
import { File } from './util';
|
|
8
|
+
export interface TranslateResult {
|
|
9
|
+
translation: string;
|
|
10
|
+
diagnostics: readonly RosettaDiagnostic[];
|
|
11
|
+
}
|
|
8
12
|
export declare function translateTypeScript(source: File, visitor: AstHandler<any>, options?: SnippetTranslatorOptions): TranslateResult;
|
|
9
13
|
/**
|
|
10
14
|
* Translate one or more TypeScript snippets into other languages
|
|
@@ -16,9 +20,8 @@ export declare class Translator {
|
|
|
16
20
|
#private;
|
|
17
21
|
private readonly includeCompilerDiagnostics;
|
|
18
22
|
private readonly compiler;
|
|
19
|
-
constructor(includeCompilerDiagnostics: boolean);
|
|
20
|
-
translate(snip: TypeScriptSnippet, languages?: readonly TargetLanguage[]): TranslatedSnippet;
|
|
21
23
|
get diagnostics(): readonly RosettaDiagnostic[];
|
|
24
|
+
constructor(includeCompilerDiagnostics: boolean);
|
|
22
25
|
/**
|
|
23
26
|
* Return the snippet translator for the given snippet
|
|
24
27
|
*
|
|
@@ -26,6 +29,23 @@ export declare class Translator {
|
|
|
26
29
|
* so we don't do that anymore.
|
|
27
30
|
*/
|
|
28
31
|
translatorFor(snippet: TypeScriptSnippet): SnippetTranslator;
|
|
32
|
+
/**
|
|
33
|
+
* Translates a single snippet in its own TS context.
|
|
34
|
+
*/
|
|
35
|
+
translate(snip: TypeScriptSnippet, languages?: readonly TargetLanguage[]): TranslatedSnippet;
|
|
36
|
+
/**
|
|
37
|
+
* Translates a batch of snippets, using a shared TS context.
|
|
38
|
+
*/
|
|
39
|
+
translateSnippets(snippets: TypeScriptSnippet[], languages?: readonly TargetLanguage[]): TranslatedSnippet[];
|
|
40
|
+
private translateBatch;
|
|
41
|
+
private translateSnippet;
|
|
42
|
+
}
|
|
43
|
+
export interface ISnippetTranslator {
|
|
44
|
+
readonly diagnostics: readonly ts.Diagnostic[];
|
|
45
|
+
readonly didSuccessfullyCompile: boolean | undefined;
|
|
46
|
+
renderUsing(visitor: AstHandler<any>): string;
|
|
47
|
+
syntaxKindCounter(): Partial<Record<ts.SyntaxKind, number>>;
|
|
48
|
+
fqnsReferenced(): string[];
|
|
29
49
|
}
|
|
30
50
|
export interface SnippetTranslatorOptions extends AstRendererOptions {
|
|
31
51
|
/**
|
|
@@ -41,9 +61,55 @@ export interface SnippetTranslatorOptions extends AstRendererOptions {
|
|
|
41
61
|
*/
|
|
42
62
|
readonly includeCompilerDiagnostics?: boolean;
|
|
43
63
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Internal implementation of a single TypeScript snippet translator.
|
|
66
|
+
*
|
|
67
|
+
* Consumers should either use `SnippetTranslator` or `BatchSnippetTranslator`.
|
|
68
|
+
*/
|
|
69
|
+
declare class InternalSnippetTranslator implements ISnippetTranslator {
|
|
70
|
+
private readonly compilation;
|
|
71
|
+
private readonly options;
|
|
72
|
+
readonly translateDiagnostics: ts.Diagnostic[];
|
|
73
|
+
readonly compileDiagnostics: ts.Diagnostic[];
|
|
74
|
+
private readonly visibleSpans;
|
|
75
|
+
private readonly tryCompile;
|
|
76
|
+
private readonly submoduleReferences;
|
|
77
|
+
constructor(snippet: TypeScriptSnippet, compilation: CompilationResult, options: SnippetTranslatorOptions);
|
|
78
|
+
/**
|
|
79
|
+
* Returns a boolean if compilation was attempted, and undefined if it was not.
|
|
80
|
+
*/
|
|
81
|
+
get didSuccessfullyCompile(): boolean | undefined;
|
|
82
|
+
renderUsing(visitor: AstHandler<any>): string;
|
|
83
|
+
syntaxKindCounter(): Partial<Record<ts.SyntaxKind, number>>;
|
|
84
|
+
fqnsReferenced(): string[];
|
|
85
|
+
get diagnostics(): readonly ts.Diagnostic[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Translate a single TypeScript snippet
|
|
89
|
+
*/
|
|
90
|
+
export declare class SnippetTranslator extends InternalSnippetTranslator {
|
|
91
|
+
constructor(snippet: TypeScriptSnippet, options?: SnippetTranslatorOptions);
|
|
92
|
+
}
|
|
93
|
+
export interface BatchSnippetTranslatorOptions extends SnippetTranslatorOptions {
|
|
94
|
+
/**
|
|
95
|
+
* What directory to pretend the file is in (system parameter)
|
|
96
|
+
*
|
|
97
|
+
* Attached when compiling a literate file, as they compile in
|
|
98
|
+
* the location where they are stored.
|
|
99
|
+
*
|
|
100
|
+
* @default - current working directory
|
|
101
|
+
*/
|
|
102
|
+
readonly compilationDirectory?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Translate a single TypeScript snippet
|
|
106
|
+
*/
|
|
107
|
+
export declare class BatchSnippetTranslator {
|
|
108
|
+
private readonly snippets;
|
|
109
|
+
private readonly options;
|
|
110
|
+
private readonly compilation;
|
|
111
|
+
constructor(snippets: TypeScriptSnippet[], options?: BatchSnippetTranslatorOptions);
|
|
112
|
+
[Symbol.iterator](): Generator<[TypeScriptSnippet, ISnippetTranslator], void, unknown>;
|
|
47
113
|
}
|
|
48
114
|
/**
|
|
49
115
|
* A translation of a TypeScript diagnostic into a data-only representation for Rosetta
|
|
@@ -71,29 +137,9 @@ export interface RosettaDiagnostic {
|
|
|
71
137
|
readonly formattedMessage: string;
|
|
72
138
|
}
|
|
73
139
|
export declare function makeRosettaDiagnostic(isError: boolean, formattedMessage: string): RosettaDiagnostic;
|
|
74
|
-
/**
|
|
75
|
-
* Translate a single TypeScript snippet
|
|
76
|
-
*/
|
|
77
|
-
export declare class SnippetTranslator {
|
|
78
|
-
private readonly options;
|
|
79
|
-
readonly translateDiagnostics: ts.Diagnostic[];
|
|
80
|
-
readonly compileDiagnostics: ts.Diagnostic[];
|
|
81
|
-
private readonly visibleSpans;
|
|
82
|
-
private readonly compilation;
|
|
83
|
-
private readonly tryCompile;
|
|
84
|
-
private readonly submoduleReferences;
|
|
85
|
-
constructor(snippet: TypeScriptSnippet, options?: SnippetTranslatorOptions);
|
|
86
|
-
/**
|
|
87
|
-
* Returns a boolean if compilation was attempted, and undefined if it was not.
|
|
88
|
-
*/
|
|
89
|
-
get didSuccessfullyCompile(): boolean | undefined;
|
|
90
|
-
renderUsing(visitor: AstHandler<any>): string;
|
|
91
|
-
syntaxKindCounter(): Partial<Record<ts.SyntaxKind, number>>;
|
|
92
|
-
fqnsReferenced(): string[];
|
|
93
|
-
get diagnostics(): readonly ts.Diagnostic[];
|
|
94
|
-
}
|
|
95
140
|
/**
|
|
96
141
|
* Turn TypeScript diagnostics into Rosetta diagnostics
|
|
97
142
|
*/
|
|
98
143
|
export declare function rosettaDiagFromTypescript(diag: ts.Diagnostic): RosettaDiagnostic;
|
|
144
|
+
export {};
|
|
99
145
|
//# sourceMappingURL=translate.d.ts.map
|
package/lib/translate.js
CHANGED
|
@@ -6,10 +6,11 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
6
6
|
};
|
|
7
7
|
var _Translator_diagnostics;
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.SnippetTranslator = exports.Translator = void 0;
|
|
9
|
+
exports.BatchSnippetTranslator = exports.SnippetTranslator = exports.Translator = void 0;
|
|
10
10
|
exports.translateTypeScript = translateTypeScript;
|
|
11
11
|
exports.makeRosettaDiagnostic = makeRosettaDiagnostic;
|
|
12
12
|
exports.rosettaDiagFromTypescript = rosettaDiagFromTypescript;
|
|
13
|
+
const path = require("node:path");
|
|
13
14
|
const node_util_1 = require("node:util");
|
|
14
15
|
const ts = require("typescript");
|
|
15
16
|
const languages_1 = require("./languages");
|
|
@@ -42,80 +43,111 @@ function translateTypeScript(source, visitor, options = {}) {
|
|
|
42
43
|
* translation.
|
|
43
44
|
*/
|
|
44
45
|
class Translator {
|
|
46
|
+
get diagnostics() {
|
|
47
|
+
return ts.sortAndDeduplicateDiagnostics(__classPrivateFieldGet(this, _Translator_diagnostics, "f")).map(rosettaDiagFromTypescript);
|
|
48
|
+
}
|
|
45
49
|
constructor(includeCompilerDiagnostics) {
|
|
46
50
|
this.includeCompilerDiagnostics = includeCompilerDiagnostics;
|
|
47
51
|
this.compiler = new ts_compiler_1.TypeScriptCompiler();
|
|
48
|
-
// eslint-disable-next-line @typescript-eslint/explicit-member-accessibility
|
|
49
52
|
_Translator_diagnostics.set(this, []);
|
|
50
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Return the snippet translator for the given snippet
|
|
56
|
+
*
|
|
57
|
+
* We used to cache these, but each translator holds on to quite a bit of memory,
|
|
58
|
+
* so we don't do that anymore.
|
|
59
|
+
*/
|
|
60
|
+
translatorFor(snippet) {
|
|
61
|
+
const translator = new SnippetTranslator(snippet, {
|
|
62
|
+
compiler: this.compiler,
|
|
63
|
+
includeCompilerDiagnostics: this.includeCompilerDiagnostics,
|
|
64
|
+
});
|
|
65
|
+
return translator;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Translates a single snippet in its own TS context.
|
|
69
|
+
*/
|
|
51
70
|
translate(snip, languages = Object.values(languages_1.TargetLanguage)) {
|
|
71
|
+
const start = performance.now();
|
|
52
72
|
logging.debug(`Translating ${(0, key_1.snippetKey)(snip)} ${(0, node_util_1.inspect)(snip.parameters ?? {})}`);
|
|
53
73
|
const translator = this.translatorFor(snip);
|
|
74
|
+
const translated = this.translateSnippet(snip, translator, languages);
|
|
75
|
+
const duration = performance.now() - start;
|
|
76
|
+
logging.debug(`Completed ${(0, key_1.snippetKey)(snip)} ${(0, node_util_1.inspect)({
|
|
77
|
+
duration: `${(duration / 1000).toFixed(2)}s`,
|
|
78
|
+
})}`);
|
|
79
|
+
return translated;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Translates a batch of snippets, using a shared TS context.
|
|
83
|
+
*/
|
|
84
|
+
translateSnippets(snippets, languages = Object.values(languages_1.TargetLanguage)) {
|
|
85
|
+
const start = performance.now();
|
|
86
|
+
logging.debug(`Translating batch of ${snippets.length} snippets`);
|
|
87
|
+
const res = this.translateBatch(snippets, languages);
|
|
88
|
+
const duration = performance.now() - start;
|
|
89
|
+
logging.debug(`Completed batch ${(0, node_util_1.inspect)({
|
|
90
|
+
duration: `${(duration / 1000).toFixed(2)}s`,
|
|
91
|
+
})}`);
|
|
92
|
+
return res;
|
|
93
|
+
}
|
|
94
|
+
translateBatch(snippets, languages = Object.values(languages_1.TargetLanguage)) {
|
|
95
|
+
const translatedSnippets = [];
|
|
96
|
+
const batchTranslator = new BatchSnippetTranslator(snippets, {
|
|
97
|
+
compiler: this.compiler,
|
|
98
|
+
includeCompilerDiagnostics: this.includeCompilerDiagnostics,
|
|
99
|
+
});
|
|
100
|
+
for (const [snippet, translator] of batchTranslator) {
|
|
101
|
+
translatedSnippets.push(this.translateSnippet(snippet, translator, languages));
|
|
102
|
+
}
|
|
103
|
+
return translatedSnippets;
|
|
104
|
+
}
|
|
105
|
+
translateSnippet(snippet, translator, languages) {
|
|
54
106
|
const translations = (0, util_1.mkDict)(languages.flatMap((lang, idx, array) => {
|
|
55
107
|
if (array.slice(0, idx).includes(lang)) {
|
|
56
|
-
// This language was duplicated in the request... we'll skip that here...
|
|
57
108
|
return [];
|
|
58
109
|
}
|
|
59
110
|
const languageConverterFactory = languages_1.TARGET_LANGUAGES[lang];
|
|
60
111
|
const translated = translator.renderUsing(languageConverterFactory.createVisitor());
|
|
61
112
|
return [[lang, { source: translated, version: languageConverterFactory.version }]];
|
|
62
113
|
}));
|
|
63
|
-
if (
|
|
114
|
+
if (snippet.parameters?.infused === undefined) {
|
|
64
115
|
__classPrivateFieldGet(this, _Translator_diagnostics, "f").push(...translator.diagnostics);
|
|
65
116
|
}
|
|
66
117
|
return tablets_1.TranslatedSnippet.fromSchema({
|
|
67
118
|
translations: {
|
|
68
119
|
...translations,
|
|
69
|
-
[schema_1.ORIGINAL_SNIPPET_KEY]: { source:
|
|
120
|
+
[schema_1.ORIGINAL_SNIPPET_KEY]: { source: snippet.visibleSource, version: '0' },
|
|
70
121
|
},
|
|
71
|
-
location:
|
|
122
|
+
location: snippet.location,
|
|
72
123
|
didCompile: translator.didSuccessfullyCompile,
|
|
73
124
|
fqnsReferenced: translator.fqnsReferenced(),
|
|
74
|
-
fullSource: (0, snippet_1.completeSource)(
|
|
125
|
+
fullSource: (0, snippet_1.completeSource)(snippet),
|
|
75
126
|
syntaxKindCounter: translator.syntaxKindCounter(),
|
|
76
127
|
});
|
|
77
128
|
}
|
|
78
|
-
get diagnostics() {
|
|
79
|
-
return ts.sortAndDeduplicateDiagnostics(__classPrivateFieldGet(this, _Translator_diagnostics, "f")).map(rosettaDiagFromTypescript);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Return the snippet translator for the given snippet
|
|
83
|
-
*
|
|
84
|
-
* We used to cache these, but each translator holds on to quite a bit of memory,
|
|
85
|
-
* so we don't do that anymore.
|
|
86
|
-
*/
|
|
87
|
-
translatorFor(snippet) {
|
|
88
|
-
const translator = new SnippetTranslator(snippet, {
|
|
89
|
-
compiler: this.compiler,
|
|
90
|
-
includeCompilerDiagnostics: this.includeCompilerDiagnostics,
|
|
91
|
-
});
|
|
92
|
-
return translator;
|
|
93
|
-
}
|
|
94
129
|
}
|
|
95
130
|
exports.Translator = Translator;
|
|
96
131
|
_Translator_diagnostics = new WeakMap();
|
|
97
|
-
function makeRosettaDiagnostic(isError, formattedMessage) {
|
|
98
|
-
return { isError, formattedMessage, isFromStrictAssembly: false };
|
|
99
|
-
}
|
|
100
132
|
/**
|
|
101
|
-
*
|
|
133
|
+
* Internal implementation of a single TypeScript snippet translator.
|
|
134
|
+
*
|
|
135
|
+
* Consumers should either use `SnippetTranslator` or `BatchSnippetTranslator`.
|
|
102
136
|
*/
|
|
103
|
-
class
|
|
104
|
-
constructor(snippet, options
|
|
137
|
+
class InternalSnippetTranslator {
|
|
138
|
+
constructor(snippet, compilation, options) {
|
|
139
|
+
this.compilation = compilation;
|
|
105
140
|
this.options = options;
|
|
106
141
|
this.translateDiagnostics = [];
|
|
107
142
|
this.compileDiagnostics = [];
|
|
108
|
-
const compiler = options.compiler ?? new ts_compiler_1.TypeScriptCompiler();
|
|
109
|
-
const source = (0, snippet_1.completeSource)(snippet);
|
|
110
|
-
const fakeCurrentDirectory = snippet.parameters?.[snippet_1.SnippetParameters.$COMPILATION_DIRECTORY] ?? process.cwd();
|
|
111
|
-
this.compilation = compiler.compileInMemory(removeSlashes((0, snippet_1.formatLocation)(snippet.location)), source, fakeCurrentDirectory);
|
|
112
143
|
// Respect '/// !hide' and '/// !show' directives
|
|
113
|
-
|
|
144
|
+
// Use the actual compiled source text to ensure spans match the AST
|
|
145
|
+
this.visibleSpans = visible_spans_1.Spans.visibleSpansFromSource(compilation.rootFile.text);
|
|
114
146
|
// Find submodule references on explicit imports
|
|
115
|
-
this.submoduleReferences = submodule_reference_1.SubmoduleReference.inSourceFile(
|
|
147
|
+
this.submoduleReferences = submodule_reference_1.SubmoduleReference.inSourceFile(compilation.rootFile, this.compilation.program.getTypeChecker());
|
|
116
148
|
// This makes it about 5x slower, so only do it on demand
|
|
117
149
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
118
|
-
this.tryCompile = (options.includeCompilerDiagnostics || snippet.strict) ?? false;
|
|
150
|
+
this.tryCompile = (this.options.includeCompilerDiagnostics || snippet.strict) ?? false;
|
|
119
151
|
if (this.tryCompile) {
|
|
120
152
|
const program = this.compilation.program;
|
|
121
153
|
const diagnostics = [
|
|
@@ -132,26 +164,6 @@ class SnippetTranslator {
|
|
|
132
164
|
}
|
|
133
165
|
this.compileDiagnostics.push(...diagnostics);
|
|
134
166
|
}
|
|
135
|
-
/**
|
|
136
|
-
* Intercepts all exceptions thrown by the wrapped call, and logs them to
|
|
137
|
-
* console.error instead of re-throwing, then returns an empty array. This
|
|
138
|
-
* is here to avoid compiler crashes due to broken code examples that cause
|
|
139
|
-
* the TypeScript compiler to hit a "Debug Failure".
|
|
140
|
-
*/
|
|
141
|
-
function neverThrowing(call) {
|
|
142
|
-
return (...args) => {
|
|
143
|
-
try {
|
|
144
|
-
return call(...args);
|
|
145
|
-
}
|
|
146
|
-
catch (err) {
|
|
147
|
-
const isExpectedTypescriptError = err.message.includes('Debug Failure');
|
|
148
|
-
if (!isExpectedTypescriptError) {
|
|
149
|
-
console.error(`Failed to execute ${call.name}: ${err}`);
|
|
150
|
-
}
|
|
151
|
-
return [];
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
167
|
}
|
|
156
168
|
/**
|
|
157
169
|
* Returns a boolean if compilation was attempted, and undefined if it was not.
|
|
@@ -181,13 +193,87 @@ class SnippetTranslator {
|
|
|
181
193
|
return ts.sortAndDeduplicateDiagnostics(this.compileDiagnostics.concat(this.translateDiagnostics));
|
|
182
194
|
}
|
|
183
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Translate a single TypeScript snippet
|
|
198
|
+
*/
|
|
199
|
+
class SnippetTranslator extends InternalSnippetTranslator {
|
|
200
|
+
constructor(snippet, options = {}) {
|
|
201
|
+
const compiler = options.compiler ?? new ts_compiler_1.TypeScriptCompiler();
|
|
202
|
+
const source = (0, snippet_1.completeSource)(snippet);
|
|
203
|
+
const fakeCurrentDirectory = snippet.parameters?.[snippet_1.SnippetParameters.$COMPILATION_DIRECTORY] ?? process.cwd();
|
|
204
|
+
const compilation = compiler.compileBatchInMemory([
|
|
205
|
+
{
|
|
206
|
+
filename: removeSlashes((0, snippet_1.formatLocation)(snippet.location)),
|
|
207
|
+
contents: source,
|
|
208
|
+
},
|
|
209
|
+
], fakeCurrentDirectory);
|
|
210
|
+
super(snippet, {
|
|
211
|
+
program: compilation.program,
|
|
212
|
+
rootFile: compilation.rootFiles[0],
|
|
213
|
+
}, options);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
184
216
|
exports.SnippetTranslator = SnippetTranslator;
|
|
217
|
+
/**
|
|
218
|
+
* Translate a single TypeScript snippet
|
|
219
|
+
*/
|
|
220
|
+
class BatchSnippetTranslator {
|
|
221
|
+
constructor(snippets, options = {}) {
|
|
222
|
+
this.snippets = snippets;
|
|
223
|
+
this.options = options;
|
|
224
|
+
const compiler = options.compiler ?? new ts_compiler_1.TypeScriptCompiler();
|
|
225
|
+
const workingDir = options.compilationDirectory ?? process.cwd();
|
|
226
|
+
const sources = snippets.map((snippet) => {
|
|
227
|
+
const snippetLoc = snippet.parameters?.[snippet_1.SnippetParameters.$COMPILATION_DIRECTORY];
|
|
228
|
+
const filename = removeSlashes((0, snippet_1.formatLocation)(snippet.location));
|
|
229
|
+
return {
|
|
230
|
+
filename: snippetLoc ? path.relative(workingDir, path.join(snippetLoc, filename)) : filename,
|
|
231
|
+
contents: (0, snippet_1.completeSource)(snippet),
|
|
232
|
+
};
|
|
233
|
+
});
|
|
234
|
+
this.compilation = compiler.compileBatchInMemory(sources, workingDir);
|
|
235
|
+
}
|
|
236
|
+
*[Symbol.iterator]() {
|
|
237
|
+
for (const [idx, snippet] of this.snippets.entries()) {
|
|
238
|
+
const rootFile = this.compilation.rootFiles[idx];
|
|
239
|
+
const translator = new InternalSnippetTranslator(snippet, {
|
|
240
|
+
program: this.compilation.program,
|
|
241
|
+
rootFile,
|
|
242
|
+
}, this.options);
|
|
243
|
+
yield [snippet, translator];
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
exports.BatchSnippetTranslator = BatchSnippetTranslator;
|
|
248
|
+
/**
|
|
249
|
+
* Intercepts all exceptions thrown by the wrapped call, and logs them to
|
|
250
|
+
* console.error instead of re-throwing, then returns an empty array. This
|
|
251
|
+
* is here to avoid compiler crashes due to broken code examples that cause
|
|
252
|
+
* the TypeScript compiler to hit a "Debug Failure".
|
|
253
|
+
*/
|
|
254
|
+
function neverThrowing(call) {
|
|
255
|
+
return (...args) => {
|
|
256
|
+
try {
|
|
257
|
+
return call(...args);
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
const isExpectedTypescriptError = err.message.includes('Debug Failure');
|
|
261
|
+
if (!isExpectedTypescriptError) {
|
|
262
|
+
console.error(`Failed to execute ${call.name}: ${err}`);
|
|
263
|
+
}
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
185
268
|
/**
|
|
186
269
|
* Hide diagnostics that are rosetta-sourced if they are reported against a non-visible span
|
|
187
270
|
*/
|
|
188
271
|
function filterVisibleDiagnostics(diags, visibleSpans) {
|
|
189
272
|
return diags.filter((d) => d.source !== 'rosetta' || d.start === undefined || visibleSpans.containsPosition(d.start));
|
|
190
273
|
}
|
|
274
|
+
function makeRosettaDiagnostic(isError, formattedMessage) {
|
|
275
|
+
return { isError, formattedMessage, isFromStrictAssembly: false };
|
|
276
|
+
}
|
|
191
277
|
/**
|
|
192
278
|
* Turn TypeScript diagnostics into Rosetta diagnostics
|
|
193
279
|
*/
|
package/lib/translate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":"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","sourcesContent":["import { inspect } from 'node:util';\nimport * as ts from 'typescript';\n\nimport { TARGET_LANGUAGES, TargetLanguage } from './languages';\nimport { RecordReferencesVisitor } from './languages/record-references';\nimport { supportsTransitiveSubmoduleAccess } from './languages/target-language';\nimport * as logging from './logging';\nimport { renderTree } from './o-tree';\nimport { AstRenderer, AstHandler, AstRendererOptions } from './renderer';\nimport { TypeScriptSnippet, completeSource, SnippetParameters, formatLocation } from './snippet';\nimport { SubmoduleReference, SubmoduleReferenceMap } from './submodule-reference';\nimport { snippetKey } from './tablets/key';\nimport { ORIGINAL_SNIPPET_KEY } from './tablets/schema';\nimport { TranslatedSnippet } from './tablets/tablets';\nimport { SyntaxKindCounter } from './typescript/syntax-kind-counter';\nimport { TypeScriptCompiler, CompilationResult } from './typescript/ts-compiler';\nimport { Spans } from './typescript/visible-spans';\nimport { annotateStrictDiagnostic, File, hasStrictBranding, mkDict } from './util';\n\nexport function translateTypeScript(\n source: File,\n visitor: AstHandler<any>,\n options: SnippetTranslatorOptions = {},\n): TranslateResult {\n const translator = new SnippetTranslator(\n { visibleSource: source.contents, location: { api: { api: 'file', fileName: source.fileName } } },\n options,\n );\n const translated = translator.renderUsing(visitor);\n\n return {\n translation: translated,\n diagnostics: translator.diagnostics.map(rosettaDiagFromTypescript),\n };\n}\n\n/**\n * Translate one or more TypeScript snippets into other languages\n *\n * Can be configured to fully typecheck the samples, or perform only syntactical\n * translation.\n */\nexport class Translator {\n private readonly compiler = new TypeScriptCompiler();\n // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility\n #diagnostics: ts.Diagnostic[] = [];\n\n public constructor(private readonly includeCompilerDiagnostics: boolean) {}\n\n public translate(snip: TypeScriptSnippet, languages: readonly TargetLanguage[] = Object.values(TargetLanguage)) {\n logging.debug(`Translating ${snippetKey(snip)} ${inspect(snip.parameters ?? {})}`);\n const translator = this.translatorFor(snip);\n\n const translations = mkDict(\n languages.flatMap((lang, idx, array) => {\n if (array.slice(0, idx).includes(lang)) {\n // This language was duplicated in the request... we'll skip that here...\n return [];\n }\n const languageConverterFactory = TARGET_LANGUAGES[lang];\n const translated = translator.renderUsing(languageConverterFactory.createVisitor());\n return [[lang, { source: translated, version: languageConverterFactory.version }] as const];\n }),\n );\n\n if (snip.parameters?.infused === undefined) {\n this.#diagnostics.push(...translator.diagnostics);\n }\n\n return TranslatedSnippet.fromSchema({\n translations: {\n ...translations,\n [ORIGINAL_SNIPPET_KEY]: { source: snip.visibleSource, version: '0' },\n },\n location: snip.location,\n didCompile: translator.didSuccessfullyCompile,\n fqnsReferenced: translator.fqnsReferenced(),\n fullSource: completeSource(snip),\n syntaxKindCounter: translator.syntaxKindCounter(),\n });\n }\n\n public get diagnostics(): readonly RosettaDiagnostic[] {\n return ts.sortAndDeduplicateDiagnostics(this.#diagnostics).map(rosettaDiagFromTypescript);\n }\n\n /**\n * Return the snippet translator for the given snippet\n *\n * We used to cache these, but each translator holds on to quite a bit of memory,\n * so we don't do that anymore.\n */\n public translatorFor(snippet: TypeScriptSnippet) {\n const translator = new SnippetTranslator(snippet, {\n compiler: this.compiler,\n includeCompilerDiagnostics: this.includeCompilerDiagnostics,\n });\n return translator;\n }\n}\n\nexport interface SnippetTranslatorOptions extends AstRendererOptions {\n /**\n * Re-use the given compiler if given\n */\n readonly compiler?: TypeScriptCompiler;\n\n /**\n * Include compiler errors in return diagnostics\n *\n * If false, only translation diagnostics will be returned.\n *\n * @default false\n */\n readonly includeCompilerDiagnostics?: boolean;\n}\n\nexport interface TranslateResult {\n translation: string;\n diagnostics: readonly RosettaDiagnostic[];\n}\n\n/**\n * A translation of a TypeScript diagnostic into a data-only representation for Rosetta\n *\n * We cannot use the original `ts.Diagnostic` since it holds on to way too much\n * state (the source file and by extension the entire parse tree), which grows\n * too big to be properly serialized by a worker and also takes too much memory.\n *\n * Reduce it down to only the information we need.\n */\nexport interface RosettaDiagnostic {\n /**\n * If this is an error diagnostic or not\n */\n readonly isError: boolean;\n\n /**\n * If the diagnostic was emitted from an assembly that has its 'strict' flag set\n */\n readonly isFromStrictAssembly: boolean;\n\n /**\n * The formatted message, ready to be printed (will have colors and newlines in it)\n *\n * Ends in a newline.\n */\n readonly formattedMessage: string;\n}\n\nexport function makeRosettaDiagnostic(isError: boolean, formattedMessage: string): RosettaDiagnostic {\n return { isError, formattedMessage, isFromStrictAssembly: false };\n}\n\n/**\n * Translate a single TypeScript snippet\n */\nexport class SnippetTranslator {\n public readonly translateDiagnostics: ts.Diagnostic[] = [];\n public readonly compileDiagnostics: ts.Diagnostic[] = [];\n private readonly visibleSpans: Spans;\n private readonly compilation!: CompilationResult;\n private readonly tryCompile: boolean;\n private readonly submoduleReferences: SubmoduleReferenceMap;\n\n public constructor(snippet: TypeScriptSnippet, private readonly options: SnippetTranslatorOptions = {}) {\n const compiler = options.compiler ?? new TypeScriptCompiler();\n const source = completeSource(snippet);\n const fakeCurrentDirectory = snippet.parameters?.[SnippetParameters.$COMPILATION_DIRECTORY] ?? process.cwd();\n this.compilation = compiler.compileInMemory(\n removeSlashes(formatLocation(snippet.location)),\n source,\n fakeCurrentDirectory,\n );\n\n // Respect '/// !hide' and '/// !show' directives\n this.visibleSpans = Spans.visibleSpansFromSource(source);\n\n // Find submodule references on explicit imports\n this.submoduleReferences = SubmoduleReference.inSourceFile(\n this.compilation.rootFile,\n this.compilation.program.getTypeChecker(),\n );\n\n // This makes it about 5x slower, so only do it on demand\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n this.tryCompile = (options.includeCompilerDiagnostics || snippet.strict) ?? false;\n if (this.tryCompile) {\n const program = this.compilation.program;\n const diagnostics = [\n ...neverThrowing(program.getGlobalDiagnostics)(),\n ...neverThrowing(program.getSyntacticDiagnostics)(this.compilation.rootFile),\n ...neverThrowing(program.getDeclarationDiagnostics)(this.compilation.rootFile),\n ...neverThrowing(program.getSemanticDiagnostics)(this.compilation.rootFile),\n ];\n if (snippet.strict) {\n // In a strict assembly, so we'll need to brand all diagnostics here...\n for (const diag of diagnostics) {\n annotateStrictDiagnostic(diag);\n }\n }\n this.compileDiagnostics.push(...diagnostics);\n }\n\n /**\n * Intercepts all exceptions thrown by the wrapped call, and logs them to\n * console.error instead of re-throwing, then returns an empty array. This\n * is here to avoid compiler crashes due to broken code examples that cause\n * the TypeScript compiler to hit a \"Debug Failure\".\n */\n function neverThrowing<A extends unknown[], R>(call: (...args: A) => readonly R[]): (...args: A) => readonly R[] {\n return (...args: A) => {\n try {\n return call(...args);\n } catch (err: any) {\n const isExpectedTypescriptError = err.message.includes('Debug Failure');\n\n if (!isExpectedTypescriptError) {\n console.error(`Failed to execute ${call.name}: ${err}`);\n }\n\n return [];\n }\n };\n }\n }\n\n /**\n * Returns a boolean if compilation was attempted, and undefined if it was not.\n */\n public get didSuccessfullyCompile() {\n return this.tryCompile ? this.compileDiagnostics.length === 0 : undefined;\n }\n\n public renderUsing(visitor: AstHandler<any>) {\n const converter = new AstRenderer(\n this.compilation.rootFile,\n this.compilation.program.getTypeChecker(),\n visitor,\n this.options,\n // If we support transitive submodule access, don't provide a submodule reference map.\n supportsTransitiveSubmoduleAccess(visitor.language) ? undefined : this.submoduleReferences,\n );\n const converted = converter.convert(this.compilation.rootFile);\n this.translateDiagnostics.push(...filterVisibleDiagnostics(converter.diagnostics, this.visibleSpans));\n return renderTree(converted, { indentChar: visitor.indentChar, visibleSpans: this.visibleSpans });\n }\n\n public syntaxKindCounter(): Partial<Record<ts.SyntaxKind, number>> {\n const kindCounter = new SyntaxKindCounter(this.visibleSpans);\n return kindCounter.countKinds(this.compilation.rootFile);\n }\n\n public fqnsReferenced() {\n const visitor = new RecordReferencesVisitor(this.visibleSpans);\n const converter = new AstRenderer(\n this.compilation.rootFile,\n this.compilation.program.getTypeChecker(),\n visitor,\n this.options,\n this.submoduleReferences,\n );\n converter.convert(this.compilation.rootFile);\n return visitor.fqnsReferenced();\n }\n\n public get diagnostics(): readonly ts.Diagnostic[] {\n return ts.sortAndDeduplicateDiagnostics(this.compileDiagnostics.concat(this.translateDiagnostics));\n }\n}\n\n/**\n * Hide diagnostics that are rosetta-sourced if they are reported against a non-visible span\n */\nfunction filterVisibleDiagnostics(diags: readonly ts.Diagnostic[], visibleSpans: Spans): ts.Diagnostic[] {\n return diags.filter((d) => d.source !== 'rosetta' || d.start === undefined || visibleSpans.containsPosition(d.start));\n}\n\n/**\n * Turn TypeScript diagnostics into Rosetta diagnostics\n */\nexport function rosettaDiagFromTypescript(diag: ts.Diagnostic): RosettaDiagnostic {\n return {\n isError: diag.category === ts.DiagnosticCategory.Error,\n isFromStrictAssembly: hasStrictBranding(diag),\n formattedMessage: ts.formatDiagnosticsWithColorAndContext([diag], DIAG_HOST),\n };\n}\n\nconst DIAG_HOST = {\n getCurrentDirectory() {\n return '.';\n },\n getCanonicalFileName(fileName: string) {\n return fileName;\n },\n getNewLine() {\n return '\\n';\n },\n};\n\n/**\n * Remove slashes from a \"where\" description, as the TS compiler will interpret it as a directory\n * and we can't have that for compiling literate files\n */\nfunction removeSlashes(x: string) {\n return x.replace(/\\/|\\\\/g, '.');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'node:path';\nimport { inspect } from 'node:util';\nimport * as ts from 'typescript';\n\nimport { TARGET_LANGUAGES, TargetLanguage } from './languages';\nimport { RecordReferencesVisitor } from './languages/record-references';\nimport { supportsTransitiveSubmoduleAccess } from './languages/target-language';\nimport * as logging from './logging';\nimport { renderTree } from './o-tree';\nimport { AstRenderer, AstHandler, AstRendererOptions } from './renderer';\nimport { TypeScriptSnippet, completeSource, SnippetParameters, formatLocation } from './snippet';\nimport { SubmoduleReference, SubmoduleReferenceMap } from './submodule-reference';\nimport { snippetKey } from './tablets/key';\nimport { ORIGINAL_SNIPPET_KEY } from './tablets/schema';\nimport { TranslatedSnippet } from './tablets/tablets';\nimport { SyntaxKindCounter } from './typescript/syntax-kind-counter';\nimport { TypeScriptCompiler, CompilationResult, BatchCompilationResult } from './typescript/ts-compiler';\nimport { Spans } from './typescript/visible-spans';\nimport { annotateStrictDiagnostic, File, hasStrictBranding, mkDict } from './util';\n\nexport interface TranslateResult {\n translation: string;\n diagnostics: readonly RosettaDiagnostic[];\n}\n\nexport function translateTypeScript(\n source: File,\n visitor: AstHandler<any>,\n options: SnippetTranslatorOptions = {},\n): TranslateResult {\n const translator = new SnippetTranslator(\n { visibleSource: source.contents, location: { api: { api: 'file', fileName: source.fileName } } },\n options,\n );\n const translated = translator.renderUsing(visitor);\n\n return {\n translation: translated,\n diagnostics: translator.diagnostics.map(rosettaDiagFromTypescript),\n };\n}\n\n/**\n * Translate one or more TypeScript snippets into other languages\n *\n * Can be configured to fully typecheck the samples, or perform only syntactical\n * translation.\n */\nexport class Translator {\n private readonly compiler = new TypeScriptCompiler();\n #diagnostics: ts.Diagnostic[] = [];\n\n public get diagnostics(): readonly RosettaDiagnostic[] {\n return ts.sortAndDeduplicateDiagnostics(this.#diagnostics).map(rosettaDiagFromTypescript);\n }\n\n public constructor(private readonly includeCompilerDiagnostics: boolean) {}\n\n /**\n * Return the snippet translator for the given snippet\n *\n * We used to cache these, but each translator holds on to quite a bit of memory,\n * so we don't do that anymore.\n */\n public translatorFor(snippet: TypeScriptSnippet) {\n const translator = new SnippetTranslator(snippet, {\n compiler: this.compiler,\n includeCompilerDiagnostics: this.includeCompilerDiagnostics,\n });\n return translator;\n }\n\n /**\n * Translates a single snippet in its own TS context.\n */\n public translate(snip: TypeScriptSnippet, languages: readonly TargetLanguage[] = Object.values(TargetLanguage)) {\n const start = performance.now();\n logging.debug(`Translating ${snippetKey(snip)} ${inspect(snip.parameters ?? {})}`);\n\n const translator = this.translatorFor(snip);\n const translated = this.translateSnippet(snip, translator, languages);\n\n const duration = performance.now() - start;\n logging.debug(\n `Completed ${snippetKey(snip)} ${inspect({\n duration: `${(duration / 1000).toFixed(2)}s`,\n })}`,\n );\n\n return translated;\n }\n\n /**\n * Translates a batch of snippets, using a shared TS context.\n */\n public translateSnippets(\n snippets: TypeScriptSnippet[],\n languages: readonly TargetLanguage[] = Object.values(TargetLanguage),\n ): TranslatedSnippet[] {\n const start = performance.now();\n logging.debug(`Translating batch of ${snippets.length} snippets`);\n\n const res = this.translateBatch(snippets, languages);\n\n const duration = performance.now() - start;\n logging.debug(\n `Completed batch ${inspect({\n duration: `${(duration / 1000).toFixed(2)}s`,\n })}`,\n );\n\n return res;\n }\n\n private translateBatch(\n snippets: TypeScriptSnippet[],\n languages: readonly TargetLanguage[] = Object.values(TargetLanguage),\n ): TranslatedSnippet[] {\n const translatedSnippets: TranslatedSnippet[] = [];\n\n const batchTranslator = new BatchSnippetTranslator(snippets, {\n compiler: this.compiler,\n includeCompilerDiagnostics: this.includeCompilerDiagnostics,\n });\n\n for (const [snippet, translator] of batchTranslator) {\n translatedSnippets.push(this.translateSnippet(snippet, translator, languages));\n }\n\n return translatedSnippets;\n }\n\n private translateSnippet(\n snippet: TypeScriptSnippet,\n translator: ISnippetTranslator,\n languages: readonly TargetLanguage[],\n ): TranslatedSnippet {\n const translations = mkDict(\n languages.flatMap((lang, idx, array) => {\n if (array.slice(0, idx).includes(lang)) {\n return [];\n }\n const languageConverterFactory = TARGET_LANGUAGES[lang];\n const translated = translator.renderUsing(languageConverterFactory.createVisitor());\n return [[lang, { source: translated, version: languageConverterFactory.version }] as const];\n }),\n );\n\n if (snippet.parameters?.infused === undefined) {\n this.#diagnostics.push(...translator.diagnostics);\n }\n\n return TranslatedSnippet.fromSchema({\n translations: {\n ...translations,\n [ORIGINAL_SNIPPET_KEY]: { source: snippet.visibleSource, version: '0' },\n },\n location: snippet.location,\n didCompile: translator.didSuccessfullyCompile,\n fqnsReferenced: translator.fqnsReferenced(),\n fullSource: completeSource(snippet),\n syntaxKindCounter: translator.syntaxKindCounter(),\n });\n }\n}\n\nexport interface ISnippetTranslator {\n readonly diagnostics: readonly ts.Diagnostic[];\n readonly didSuccessfullyCompile: boolean | undefined;\n\n renderUsing(visitor: AstHandler<any>): string;\n syntaxKindCounter(): Partial<Record<ts.SyntaxKind, number>>;\n fqnsReferenced(): string[];\n}\n\nexport interface SnippetTranslatorOptions extends AstRendererOptions {\n /**\n * Re-use the given compiler if given\n */\n readonly compiler?: TypeScriptCompiler;\n\n /**\n * Include compiler errors in return diagnostics\n *\n * If false, only translation diagnostics will be returned.\n *\n * @default false\n */\n readonly includeCompilerDiagnostics?: boolean;\n}\n\n/**\n * Internal implementation of a single TypeScript snippet translator.\n *\n * Consumers should either use `SnippetTranslator` or `BatchSnippetTranslator`.\n */\nclass InternalSnippetTranslator implements ISnippetTranslator {\n public readonly translateDiagnostics: ts.Diagnostic[] = [];\n public readonly compileDiagnostics: ts.Diagnostic[] = [];\n\n private readonly visibleSpans: Spans;\n private readonly tryCompile: boolean;\n private readonly submoduleReferences: SubmoduleReferenceMap;\n\n public constructor(\n snippet: TypeScriptSnippet,\n private readonly compilation: CompilationResult,\n private readonly options: SnippetTranslatorOptions,\n ) {\n // Respect '/// !hide' and '/// !show' directives\n // Use the actual compiled source text to ensure spans match the AST\n this.visibleSpans = Spans.visibleSpansFromSource(compilation.rootFile.text);\n\n // Find submodule references on explicit imports\n this.submoduleReferences = SubmoduleReference.inSourceFile(\n compilation.rootFile,\n this.compilation.program.getTypeChecker(),\n );\n\n // This makes it about 5x slower, so only do it on demand\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n this.tryCompile = (this.options.includeCompilerDiagnostics || snippet.strict) ?? false;\n if (this.tryCompile) {\n const program = this.compilation.program;\n const diagnostics = [\n ...neverThrowing(program.getGlobalDiagnostics)(),\n ...neverThrowing(program.getSyntacticDiagnostics)(this.compilation.rootFile),\n ...neverThrowing(program.getDeclarationDiagnostics)(this.compilation.rootFile),\n ...neverThrowing(program.getSemanticDiagnostics)(this.compilation.rootFile),\n ];\n\n if (snippet.strict) {\n // In a strict assembly, so we'll need to brand all diagnostics here...\n for (const diag of diagnostics) {\n annotateStrictDiagnostic(diag);\n }\n }\n this.compileDiagnostics.push(...diagnostics);\n }\n }\n\n /**\n * Returns a boolean if compilation was attempted, and undefined if it was not.\n */\n public get didSuccessfullyCompile() {\n return this.tryCompile ? this.compileDiagnostics.length === 0 : undefined;\n }\n\n public renderUsing(visitor: AstHandler<any>) {\n const converter = new AstRenderer(\n this.compilation.rootFile,\n this.compilation.program.getTypeChecker(),\n visitor,\n this.options,\n // If we support transitive submodule access, don't provide a submodule reference map.\n supportsTransitiveSubmoduleAccess(visitor.language) ? undefined : this.submoduleReferences,\n );\n const converted = converter.convert(this.compilation.rootFile);\n this.translateDiagnostics.push(...filterVisibleDiagnostics(converter.diagnostics, this.visibleSpans));\n return renderTree(converted, { indentChar: visitor.indentChar, visibleSpans: this.visibleSpans });\n }\n\n public syntaxKindCounter(): Partial<Record<ts.SyntaxKind, number>> {\n const kindCounter = new SyntaxKindCounter(this.visibleSpans);\n return kindCounter.countKinds(this.compilation.rootFile);\n }\n\n public fqnsReferenced() {\n const visitor = new RecordReferencesVisitor(this.visibleSpans);\n const converter = new AstRenderer(\n this.compilation.rootFile,\n this.compilation.program.getTypeChecker(),\n visitor,\n this.options,\n this.submoduleReferences,\n );\n converter.convert(this.compilation.rootFile);\n return visitor.fqnsReferenced();\n }\n\n public get diagnostics(): readonly ts.Diagnostic[] {\n return ts.sortAndDeduplicateDiagnostics(this.compileDiagnostics.concat(this.translateDiagnostics));\n }\n}\n\n/**\n * Translate a single TypeScript snippet\n */\nexport class SnippetTranslator extends InternalSnippetTranslator {\n public constructor(snippet: TypeScriptSnippet, options: SnippetTranslatorOptions = {}) {\n const compiler = options.compiler ?? new TypeScriptCompiler();\n const source = completeSource(snippet);\n const fakeCurrentDirectory = snippet.parameters?.[SnippetParameters.$COMPILATION_DIRECTORY] ?? process.cwd();\n const compilation = compiler.compileBatchInMemory(\n [\n {\n filename: removeSlashes(formatLocation(snippet.location)),\n contents: source,\n },\n ],\n fakeCurrentDirectory,\n );\n\n super(\n snippet,\n {\n program: compilation.program,\n rootFile: compilation.rootFiles[0],\n },\n options,\n );\n }\n}\n\nexport interface BatchSnippetTranslatorOptions extends SnippetTranslatorOptions {\n /**\n * What directory to pretend the file is in (system parameter)\n *\n * Attached when compiling a literate file, as they compile in\n * the location where they are stored.\n *\n * @default - current working directory\n */\n readonly compilationDirectory?: string;\n}\n\n/**\n * Translate a single TypeScript snippet\n */\nexport class BatchSnippetTranslator {\n private readonly compilation: BatchCompilationResult;\n\n public constructor(\n private readonly snippets: TypeScriptSnippet[],\n private readonly options: BatchSnippetTranslatorOptions = {},\n ) {\n const compiler = options.compiler ?? new TypeScriptCompiler();\n const workingDir = options.compilationDirectory ?? process.cwd();\n\n const sources = snippets.map((snippet) => {\n const snippetLoc = snippet.parameters?.[SnippetParameters.$COMPILATION_DIRECTORY];\n const filename = removeSlashes(formatLocation(snippet.location));\n\n return {\n filename: snippetLoc ? path.relative(workingDir, path.join(snippetLoc, filename)) : filename,\n contents: completeSource(snippet),\n };\n });\n this.compilation = compiler.compileBatchInMemory(sources, workingDir);\n }\n\n *[Symbol.iterator](): Generator<[TypeScriptSnippet, ISnippetTranslator], void, unknown> {\n for (const [idx, snippet] of this.snippets.entries()) {\n const rootFile = this.compilation.rootFiles[idx];\n\n const translator: ISnippetTranslator = new InternalSnippetTranslator(\n snippet,\n {\n program: this.compilation.program,\n rootFile,\n },\n this.options,\n );\n\n yield [snippet, translator];\n }\n }\n}\n\n/**\n * Intercepts all exceptions thrown by the wrapped call, and logs them to\n * console.error instead of re-throwing, then returns an empty array. This\n * is here to avoid compiler crashes due to broken code examples that cause\n * the TypeScript compiler to hit a \"Debug Failure\".\n */\nfunction neverThrowing<A extends unknown[], R>(call: (...args: A) => readonly R[]): (...args: A) => readonly R[] {\n return (...args: A) => {\n try {\n return call(...args);\n } catch (err: any) {\n const isExpectedTypescriptError = err.message.includes('Debug Failure');\n\n if (!isExpectedTypescriptError) {\n console.error(`Failed to execute ${call.name}: ${err}`);\n }\n\n return [];\n }\n };\n}\n\n/**\n * Hide diagnostics that are rosetta-sourced if they are reported against a non-visible span\n */\nfunction filterVisibleDiagnostics(diags: readonly ts.Diagnostic[], visibleSpans: Spans): ts.Diagnostic[] {\n return diags.filter((d) => d.source !== 'rosetta' || d.start === undefined || visibleSpans.containsPosition(d.start));\n}\n\n/**\n * A translation of a TypeScript diagnostic into a data-only representation for Rosetta\n *\n * We cannot use the original `ts.Diagnostic` since it holds on to way too much\n * state (the source file and by extension the entire parse tree), which grows\n * too big to be properly serialized by a worker and also takes too much memory.\n *\n * Reduce it down to only the information we need.\n */\nexport interface RosettaDiagnostic {\n /**\n * If this is an error diagnostic or not\n */\n readonly isError: boolean;\n\n /**\n * If the diagnostic was emitted from an assembly that has its 'strict' flag set\n */\n readonly isFromStrictAssembly: boolean;\n\n /**\n * The formatted message, ready to be printed (will have colors and newlines in it)\n *\n * Ends in a newline.\n */\n readonly formattedMessage: string;\n}\n\nexport function makeRosettaDiagnostic(isError: boolean, formattedMessage: string): RosettaDiagnostic {\n return { isError, formattedMessage, isFromStrictAssembly: false };\n}\n\n/**\n * Turn TypeScript diagnostics into Rosetta diagnostics\n */\nexport function rosettaDiagFromTypescript(diag: ts.Diagnostic): RosettaDiagnostic {\n return {\n isError: diag.category === ts.DiagnosticCategory.Error,\n isFromStrictAssembly: hasStrictBranding(diag),\n formattedMessage: ts.formatDiagnosticsWithColorAndContext([diag], DIAG_HOST),\n };\n}\n\nconst DIAG_HOST = {\n getCurrentDirectory() {\n return '.';\n },\n getCanonicalFileName(fileName: string) {\n return fileName;\n },\n getNewLine() {\n return '\\n';\n },\n};\n\n/**\n * Remove slashes from a \"where\" description, as the TS compiler will interpret it as a directory\n * and we can't have that for compiling literate files\n */\nfunction removeSlashes(x: string) {\n return x.replace(/\\/|\\\\/g, '.');\n}\n"]}
|
package/lib/translate_all.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { RosettaDiagnostic } from './translate';
|
|
|
11
11
|
* Never include 'translate_all_worker' directly, only do TypeScript type references (so that in
|
|
12
12
|
* the script we may assume that 'worker_threads' successfully imports).
|
|
13
13
|
*/
|
|
14
|
-
export declare function translateAll(snippets: TypeScriptSnippet[], includeCompilerDiagnostics: boolean): Promise<TranslateAllResult>;
|
|
14
|
+
export declare function translateAll(snippets: TypeScriptSnippet[], includeCompilerDiagnostics: boolean, batchSize?: number): Promise<TranslateAllResult>;
|
|
15
15
|
export interface TranslateAllResult {
|
|
16
16
|
translatedSnippets: TranslatedSnippet[];
|
|
17
17
|
diagnostics: RosettaDiagnostic[];
|