jsii-rosetta 5.9.21-dev.0 → 5.9.22

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.
@@ -42,11 +42,11 @@ class RosettaTranslator {
42
42
  }
43
43
  async addToCache(filename) {
44
44
  const tab = await tablets_1.LanguageTablet.fromOptionalFile(filename);
45
- this.cache.addTablet(tab);
45
+ this.cache.addTranslationsFromTablet(tab);
46
46
  }
47
47
  addTabletsToCache(...tablets) {
48
48
  for (const tab of tablets) {
49
- this.cache.addTablet(tab);
49
+ this.cache.addTranslationsFromTablet(tab);
50
50
  }
51
51
  }
52
52
  hasCache() {
@@ -71,7 +71,7 @@ class RosettaTranslator {
71
71
  switch (fromCache.type) {
72
72
  case 'hit':
73
73
  if (addToTablet) {
74
- this.tablet.addSnippets(fromCache.snippet);
74
+ this.tablet.addTranslations(fromCache.snippet);
75
75
  }
76
76
  translations.push(fromCache.snippet);
77
77
  infusedCount += fromCache.infused ? 1 : 0;
@@ -141,12 +141,16 @@ class RosettaTranslator {
141
141
  }
142
142
  }
143
143
  const fingerprinted = result.translatedSnippets.map((snippet) => snippet.withFingerprint(this.fingerprinter.fingerprintAll(snippet.fqnsReferenced())));
144
+ if (process.env.DEBUG_TYPE_FINGERPRINTS) {
145
+ this.fingerprinter.writeDebugFile(process.env.DEBUG_TYPE_FINGERPRINTS);
146
+ }
144
147
  if (options?.addToTablet ?? true) {
145
- this.tablet.addSnippets(...fingerprinted);
148
+ this.tablet.addTranslations(...fingerprinted);
146
149
  }
147
150
  return {
148
151
  translatedSnippets: fingerprinted,
149
152
  diagnostics: result.diagnostics,
153
+ timings: result.timings,
150
154
  };
151
155
  }
152
156
  }
@@ -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.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"]}
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.addTranslationsFromTablet(tab);\n }\n\n public addTabletsToCache(...tablets: LanguageTablet[]) {\n for (const tab of tablets) {\n this.cache.addTranslationsFromTablet(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.addTranslations(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 (process.env.DEBUG_TYPE_FINGERPRINTS) {\n this.fingerprinter.writeDebugFile(process.env.DEBUG_TYPE_FINGERPRINTS);\n }\n\n if (options?.addToTablet ?? true) {\n this.tablet.addTranslations(...fingerprinted);\n }\n\n return {\n translatedSnippets: fingerprinted,\n diagnostics: result.diagnostics,\n timings: result.timings,\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"]}
@@ -32,26 +32,32 @@ export declare class LanguageTablet {
32
32
  compressedSource: boolean;
33
33
  private readonly snippets;
34
34
  /**
35
- * Add one or more snippets to this tablet
35
+ * Add translations from one or more snippets to this tablet
36
+ *
37
+ * WARNING: snippet metadata will not be overwritten, only translations.
36
38
  */
37
- addSnippets(...snippets: TranslatedSnippet[]): void;
39
+ addTranslations(...snippets: TranslatedSnippet[]): void;
38
40
  /**
39
- * Add one snippet to this tablet
40
- *
41
- * @deprecated use addSnippets instead
41
+ * Add one or more snippets to this tablet, overwriting matching snippets and all of their translations
42
42
  */
43
- addSnippet(snippet: TranslatedSnippet): void;
43
+ addSnippets(...snippets: TranslatedSnippet[]): void;
44
44
  get snippetKeys(): string[];
45
45
  /**
46
46
  * Add all snippets from the given tablets into this one
47
+ *
48
+ * WARNING: snippet metadata will not be overwritten, only translations.
49
+ */
50
+ addTranslationsFromTablets(...tablets: LanguageTablet[]): void;
51
+ /**
52
+ * Add all snippets from the given tablets into this one, overwriting existing snippets
47
53
  */
48
- addTablets(...tablets: LanguageTablet[]): void;
54
+ addSnippetsFromTablets(...tablets: LanguageTablet[]): void;
49
55
  /**
50
56
  * Add all snippets from the given tablet into this one
51
57
  *
52
58
  * @deprecated Use `addTablets()` instead.
53
59
  */
54
- addTablet(tablet: LanguageTablet): void;
60
+ addTranslationsFromTablet(tablet: LanguageTablet): void;
55
61
  tryGetSnippet(key: string): TranslatedSnippet | undefined;
56
62
  /**
57
63
  * Look up a single translation of a source snippet
@@ -59,33 +59,43 @@ class LanguageTablet {
59
59
  return ret;
60
60
  }
61
61
  /**
62
- * Add one or more snippets to this tablet
62
+ * Add translations from one or more snippets to this tablet
63
+ *
64
+ * WARNING: snippet metadata will not be overwritten, only translations.
63
65
  */
64
- addSnippets(...snippets) {
66
+ addTranslations(...snippets) {
65
67
  for (const snippet of snippets) {
66
68
  const existingSnippet = this.snippets[snippet.key];
67
69
  this.snippets[snippet.key] = existingSnippet ? existingSnippet.mergeTranslations(snippet) : snippet;
68
70
  }
69
71
  }
70
72
  /**
71
- * Add one snippet to this tablet
72
- *
73
- * @deprecated use addSnippets instead
73
+ * Add one or more snippets to this tablet, overwriting matching snippets and all of their translations
74
74
  */
75
- addSnippet(snippet) {
76
- this.addSnippets(snippet);
75
+ addSnippets(...snippets) {
76
+ for (const snippet of snippets) {
77
+ this.snippets[snippet.key] = snippet;
78
+ }
77
79
  }
78
80
  get snippetKeys() {
79
81
  return Object.keys(this.snippets);
80
82
  }
81
83
  /**
82
84
  * Add all snippets from the given tablets into this one
85
+ *
86
+ * WARNING: snippet metadata will not be overwritten, only translations.
83
87
  */
84
- addTablets(...tablets) {
88
+ addTranslationsFromTablets(...tablets) {
85
89
  for (const tablet of tablets) {
86
- for (const snippet of Object.values(tablet.snippets)) {
87
- this.addSnippet(snippet);
88
- }
90
+ this.addTranslations(...Object.values(tablet.snippets));
91
+ }
92
+ }
93
+ /**
94
+ * Add all snippets from the given tablets into this one, overwriting existing snippets
95
+ */
96
+ addSnippetsFromTablets(...tablets) {
97
+ for (const tablet of tablets) {
98
+ this.addSnippets(...Object.values(tablet.snippets));
89
99
  }
90
100
  }
91
101
  /**
@@ -93,8 +103,8 @@ class LanguageTablet {
93
103
  *
94
104
  * @deprecated Use `addTablets()` instead.
95
105
  */
96
- addTablet(tablet) {
97
- this.addTablets(tablet);
106
+ addTranslationsFromTablet(tablet) {
107
+ this.addTranslationsFromTablets(tablet);
98
108
  }
99
109
  tryGetSnippet(key) {
100
110
  return this.snippets[key];
@@ -1 +1 @@
1
- {"version":3,"file":"tablets.js","sourceRoot":"","sources":["../../src/tablets/tablets.ts"],"names":[],"mappings":"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","sourcesContent":["import { createReadStream, createWriteStream, existsSync, promises as fs } from 'node:fs';\nimport * as path from 'node:path';\nimport { Readable, Writable } from 'node:stream';\nimport * as zlib from 'node:zlib';\n\nimport { snippetKey } from './key';\nimport { TabletSchema, TranslatedSnippetSchema, ORIGINAL_SNIPPET_KEY } from './schema';\nimport { parse, stringify } from '../json';\nimport { TargetLanguage } from '../languages';\nimport * as logging from '../logging';\nimport { TypeScriptSnippet, SnippetLocation, completeSource } from '../snippet';\nimport { mapValues, Mutable } from '../util';\n\n// eslint-disable-next-line @typescript-eslint/no-require-imports,@typescript-eslint/no-var-requires\nconst TOOL_VERSION = require('../../package.json').version;\n\n/**\n * The default name of the tablet file\n */\nexport const DEFAULT_TABLET_NAME = '.jsii.tabl.json';\n\n/**\n * The default name of the compressed tablet file\n */\nexport const DEFAULT_TABLET_NAME_COMPRESSED = '.jsii.tabl.json.gz';\n\nexport const CURRENT_SCHEMA_VERSION = '2';\n\n/**\n * A tablet containing various snippets in multiple languages\n */\nexport class LanguageTablet {\n /**\n * Load a tablet from a file\n */\n public static async fromFile(filename: string) {\n const ret = new LanguageTablet();\n await ret.load(filename);\n return ret;\n }\n\n /**\n * Load a tablet from a file that may not exist\n *\n * Will return an empty tablet if the file does not exist\n */\n public static async fromOptionalFile(filename: string) {\n const ret = new LanguageTablet();\n if (existsSync(filename)) {\n try {\n await ret.load(filename);\n } catch (e: any) {\n logging.warn(`${filename}: ${e}`);\n }\n }\n return ret;\n }\n\n /**\n * Whether or not the LanguageTablet was loaded with a compressed source.\n * This gets used to determine if it should be compressed when saved.\n */\n public compressedSource = false;\n\n private readonly snippets: Record<string, TranslatedSnippet> = {};\n\n /**\n * Add one or more snippets to this tablet\n */\n public addSnippets(...snippets: TranslatedSnippet[]) {\n for (const snippet of snippets) {\n const existingSnippet = this.snippets[snippet.key];\n this.snippets[snippet.key] = existingSnippet ? existingSnippet.mergeTranslations(snippet) : snippet;\n }\n }\n\n /**\n * Add one snippet to this tablet\n *\n * @deprecated use addSnippets instead\n */\n public addSnippet(snippet: TranslatedSnippet) {\n this.addSnippets(snippet);\n }\n\n public get snippetKeys() {\n return Object.keys(this.snippets);\n }\n\n /**\n * Add all snippets from the given tablets into this one\n */\n public addTablets(...tablets: LanguageTablet[]) {\n for (const tablet of tablets) {\n for (const snippet of Object.values(tablet.snippets)) {\n this.addSnippet(snippet);\n }\n }\n }\n\n /**\n * Add all snippets from the given tablet into this one\n *\n * @deprecated Use `addTablets()` instead.\n */\n public addTablet(tablet: LanguageTablet) {\n this.addTablets(tablet);\n }\n\n public tryGetSnippet(key: string): TranslatedSnippet | undefined {\n return this.snippets[key];\n }\n\n /**\n * Look up a single translation of a source snippet\n *\n * @deprecated Use `lookupTranslationBySource` instead.\n */\n public lookup(typeScriptSource: TypeScriptSnippet, language: TargetLanguage): Translation | undefined {\n return this.lookupTranslationBySource(typeScriptSource, language);\n }\n\n /**\n * Look up a single translation of a source snippet\n */\n public lookupTranslationBySource(\n typeScriptSource: TypeScriptSnippet,\n language: TargetLanguage,\n ): Translation | undefined {\n const snippet = this.snippets[snippetKey(typeScriptSource)];\n return snippet?.get(language);\n }\n\n /**\n * Lookup the translated verion of a TypeScript snippet\n */\n public lookupBySource(typeScriptSource: TypeScriptSnippet): TranslatedSnippet | undefined {\n return this.snippets[snippetKey(typeScriptSource)];\n }\n\n /**\n * Load the tablet from a file. Will automatically detect if the file is\n * compressed and decompress accordingly.\n */\n public async load(filename: string) {\n let readStream: Readable;\n if (await isGzipped(filename)) {\n const gunzip = zlib.createGunzip();\n createReadStream(filename).pipe(gunzip, { end: true });\n readStream = gunzip;\n this.compressedSource = true;\n } else {\n readStream = createReadStream(filename);\n }\n\n const obj: TabletSchema = await parse(readStream);\n\n if (!obj.toolVersion || !obj.snippets) {\n throw new Error(`File '${filename}' does not seem to be a Tablet file`);\n }\n\n if (obj.version !== CURRENT_SCHEMA_VERSION) {\n // If we're ever changing the schema version in a backwards incompatible way,\n // do upconversion here.\n throw new Error(\n `Tablet file '${filename}' has schema version '${obj.version}', this program expects '${CURRENT_SCHEMA_VERSION}'`,\n );\n }\n\n Object.assign(this.snippets, mapValues(obj.snippets, TranslatedSnippet.fromSchema));\n }\n\n public get count() {\n return Object.keys(this.snippets).length;\n }\n\n public get translatedSnippets() {\n return Object.values(this.snippets);\n }\n\n /**\n * Saves the tablet schema to a file. If the compress option is passed, then\n * the schema will be gzipped before writing to the file.\n */\n public async save(filename: string, compress = false): Promise<void> {\n await fs.mkdir(path.dirname(filename), { recursive: true });\n\n const writeStream: Writable = createWriteStream(filename, { flags: 'w' });\n const gzip = compress ? zlib.createGzip() : undefined;\n\n return stringify(this.toSchema(), ...(gzip ? [gzip] : []), writeStream);\n }\n\n private toSchema(): TabletSchema {\n return {\n version: CURRENT_SCHEMA_VERSION,\n toolVersion: TOOL_VERSION,\n snippets: mapValues(this.snippets, (s) => s.snippet),\n };\n }\n}\n\n/**\n * Mutable operations on an underlying TranslatedSnippetSchema\n */\nexport class TranslatedSnippet {\n public static fromSchema(schema: TranslatedSnippetSchema) {\n if (!schema.translations[ORIGINAL_SNIPPET_KEY]) {\n throw new Error(`Input schema must have '${ORIGINAL_SNIPPET_KEY}' key set in translations`);\n }\n return new TranslatedSnippet(schema);\n }\n\n public static fromTypeScript(original: TypeScriptSnippet, didCompile?: boolean) {\n return new TranslatedSnippet({\n translations: {\n [ORIGINAL_SNIPPET_KEY]: { source: original.visibleSource, version: '0' },\n },\n didCompile: didCompile,\n location: original.location,\n fullSource: completeSource(original),\n });\n }\n\n public readonly snippet: TranslatedSnippetSchema;\n\n private readonly _snippet: Mutable<TranslatedSnippetSchema>;\n private _key?: string;\n\n private constructor(snippet: TranslatedSnippetSchema) {\n this._snippet = { ...snippet };\n this.snippet = this._snippet;\n }\n\n public get key() {\n if (this._key === undefined) {\n this._key = snippetKey(this.asTypescriptSnippet());\n }\n return this._key;\n }\n\n public get originalSource(): Translation {\n return {\n source: this.snippet.translations[ORIGINAL_SNIPPET_KEY].source,\n language: 'typescript',\n didCompile: this.snippet.didCompile,\n };\n }\n\n public addTranslation(language: TargetLanguage, translation: string, version: string): Translation {\n this.snippet.translations[language] = { source: translation, version };\n\n return {\n source: translation,\n language,\n didCompile: this.snippet.didCompile,\n };\n }\n\n public fqnsReferenced() {\n return this._snippet.fqnsReferenced ?? [];\n }\n\n public addSyntaxKindCounter(syntaxKindCounter: Record<string, number>) {\n if (!this._snippet.syntaxKindCounter) {\n this._snippet.syntaxKindCounter = {};\n }\n for (const [key, value] of Object.entries(syntaxKindCounter)) {\n const x = this._snippet.syntaxKindCounter[key] ?? 0;\n this._snippet.syntaxKindCounter[key] = value + x;\n }\n }\n\n public get languages(): TargetLanguage[] {\n return Object.keys(this.snippet.translations).filter((x) => x !== ORIGINAL_SNIPPET_KEY) as TargetLanguage[];\n }\n\n public get(language: TargetLanguage): Translation | undefined {\n const t = this.snippet.translations[language];\n return t && { source: t.source, language, didCompile: this.snippet.didCompile };\n }\n\n public mergeTranslations(other: TranslatedSnippet) {\n return new TranslatedSnippet({\n ...this.snippet,\n translations: { ...this.snippet.translations, ...other.snippet.translations },\n });\n }\n\n public withFingerprint(fp: string) {\n return new TranslatedSnippet({\n ...this.snippet,\n fqnsFingerprint: fp,\n });\n }\n\n public withLocation(location: SnippetLocation) {\n return new TranslatedSnippet({\n ...this.snippet,\n location,\n });\n }\n\n public toJSON() {\n return this._snippet;\n }\n\n private asTypescriptSnippet(): TypeScriptSnippet {\n return {\n visibleSource: this.snippet.translations[ORIGINAL_SNIPPET_KEY].source,\n location: this.snippet.location,\n };\n }\n}\n\nexport interface Translation {\n source: string;\n language: string;\n didCompile?: boolean;\n}\n\nasync function isGzipped(filename: string) {\n const openFile = await fs.open(filename, 'r');\n try {\n // Assumes that we can always read 3 bytes if there's that many in the file...\n const { bytesRead, buffer } = await openFile.read(Buffer.alloc(4), 0, 3, 0);\n return bytesRead >= 3 && buffer[0] === 0x1f && buffer[1] === 0x8b && buffer[2] === 0x08;\n } finally {\n await openFile.close();\n }\n}\n"]}
1
+ {"version":3,"file":"tablets.js","sourceRoot":"","sources":["../../src/tablets/tablets.ts"],"names":[],"mappings":"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","sourcesContent":["import { createReadStream, createWriteStream, existsSync, promises as fs } from 'node:fs';\nimport * as path from 'node:path';\nimport { Readable, Writable } from 'node:stream';\nimport * as zlib from 'node:zlib';\n\nimport { snippetKey } from './key';\nimport { TabletSchema, TranslatedSnippetSchema, ORIGINAL_SNIPPET_KEY } from './schema';\nimport { parse, stringify } from '../json';\nimport { TargetLanguage } from '../languages';\nimport * as logging from '../logging';\nimport { TypeScriptSnippet, SnippetLocation, completeSource } from '../snippet';\nimport { mapValues, Mutable } from '../util';\n\n// eslint-disable-next-line @typescript-eslint/no-require-imports,@typescript-eslint/no-var-requires\nconst TOOL_VERSION = require('../../package.json').version;\n\n/**\n * The default name of the tablet file\n */\nexport const DEFAULT_TABLET_NAME = '.jsii.tabl.json';\n\n/**\n * The default name of the compressed tablet file\n */\nexport const DEFAULT_TABLET_NAME_COMPRESSED = '.jsii.tabl.json.gz';\n\nexport const CURRENT_SCHEMA_VERSION = '2';\n\n/**\n * A tablet containing various snippets in multiple languages\n */\nexport class LanguageTablet {\n /**\n * Load a tablet from a file\n */\n public static async fromFile(filename: string) {\n const ret = new LanguageTablet();\n await ret.load(filename);\n return ret;\n }\n\n /**\n * Load a tablet from a file that may not exist\n *\n * Will return an empty tablet if the file does not exist\n */\n public static async fromOptionalFile(filename: string) {\n const ret = new LanguageTablet();\n if (existsSync(filename)) {\n try {\n await ret.load(filename);\n } catch (e: any) {\n logging.warn(`${filename}: ${e}`);\n }\n }\n return ret;\n }\n\n /**\n * Whether or not the LanguageTablet was loaded with a compressed source.\n * This gets used to determine if it should be compressed when saved.\n */\n public compressedSource = false;\n\n private readonly snippets: Record<string, TranslatedSnippet> = {};\n\n /**\n * Add translations from one or more snippets to this tablet\n *\n * WARNING: snippet metadata will not be overwritten, only translations.\n */\n public addTranslations(...snippets: TranslatedSnippet[]) {\n for (const snippet of snippets) {\n const existingSnippet = this.snippets[snippet.key];\n this.snippets[snippet.key] = existingSnippet ? existingSnippet.mergeTranslations(snippet) : snippet;\n }\n }\n\n /**\n * Add one or more snippets to this tablet, overwriting matching snippets and all of their translations\n */\n public addSnippets(...snippets: TranslatedSnippet[]) {\n for (const snippet of snippets) {\n this.snippets[snippet.key] = snippet;\n }\n }\n\n public get snippetKeys() {\n return Object.keys(this.snippets);\n }\n\n /**\n * Add all snippets from the given tablets into this one\n *\n * WARNING: snippet metadata will not be overwritten, only translations.\n */\n public addTranslationsFromTablets(...tablets: LanguageTablet[]) {\n for (const tablet of tablets) {\n this.addTranslations(...Object.values(tablet.snippets));\n }\n }\n\n /**\n * Add all snippets from the given tablets into this one, overwriting existing snippets\n */\n public addSnippetsFromTablets(...tablets: LanguageTablet[]) {\n for (const tablet of tablets) {\n this.addSnippets(...Object.values(tablet.snippets));\n }\n }\n\n /**\n * Add all snippets from the given tablet into this one\n *\n * @deprecated Use `addTablets()` instead.\n */\n public addTranslationsFromTablet(tablet: LanguageTablet) {\n this.addTranslationsFromTablets(tablet);\n }\n\n public tryGetSnippet(key: string): TranslatedSnippet | undefined {\n return this.snippets[key];\n }\n\n /**\n * Look up a single translation of a source snippet\n *\n * @deprecated Use `lookupTranslationBySource` instead.\n */\n public lookup(typeScriptSource: TypeScriptSnippet, language: TargetLanguage): Translation | undefined {\n return this.lookupTranslationBySource(typeScriptSource, language);\n }\n\n /**\n * Look up a single translation of a source snippet\n */\n public lookupTranslationBySource(\n typeScriptSource: TypeScriptSnippet,\n language: TargetLanguage,\n ): Translation | undefined {\n const snippet = this.snippets[snippetKey(typeScriptSource)];\n return snippet?.get(language);\n }\n\n /**\n * Lookup the translated verion of a TypeScript snippet\n */\n public lookupBySource(typeScriptSource: TypeScriptSnippet): TranslatedSnippet | undefined {\n return this.snippets[snippetKey(typeScriptSource)];\n }\n\n /**\n * Load the tablet from a file. Will automatically detect if the file is\n * compressed and decompress accordingly.\n */\n public async load(filename: string) {\n let readStream: Readable;\n if (await isGzipped(filename)) {\n const gunzip = zlib.createGunzip();\n createReadStream(filename).pipe(gunzip, { end: true });\n readStream = gunzip;\n this.compressedSource = true;\n } else {\n readStream = createReadStream(filename);\n }\n\n const obj: TabletSchema = await parse(readStream);\n\n if (!obj.toolVersion || !obj.snippets) {\n throw new Error(`File '${filename}' does not seem to be a Tablet file`);\n }\n\n if (obj.version !== CURRENT_SCHEMA_VERSION) {\n // If we're ever changing the schema version in a backwards incompatible way,\n // do upconversion here.\n throw new Error(\n `Tablet file '${filename}' has schema version '${obj.version}', this program expects '${CURRENT_SCHEMA_VERSION}'`,\n );\n }\n\n Object.assign(this.snippets, mapValues(obj.snippets, TranslatedSnippet.fromSchema));\n }\n\n public get count() {\n return Object.keys(this.snippets).length;\n }\n\n public get translatedSnippets() {\n return Object.values(this.snippets);\n }\n\n /**\n * Saves the tablet schema to a file. If the compress option is passed, then\n * the schema will be gzipped before writing to the file.\n */\n public async save(filename: string, compress = false): Promise<void> {\n await fs.mkdir(path.dirname(filename), { recursive: true });\n\n const writeStream: Writable = createWriteStream(filename, { flags: 'w' });\n const gzip = compress ? zlib.createGzip() : undefined;\n\n return stringify(this.toSchema(), ...(gzip ? [gzip] : []), writeStream);\n }\n\n private toSchema(): TabletSchema {\n return {\n version: CURRENT_SCHEMA_VERSION,\n toolVersion: TOOL_VERSION,\n snippets: mapValues(this.snippets, (s) => s.snippet),\n };\n }\n}\n\n/**\n * Mutable operations on an underlying TranslatedSnippetSchema\n */\nexport class TranslatedSnippet {\n public static fromSchema(schema: TranslatedSnippetSchema) {\n if (!schema.translations[ORIGINAL_SNIPPET_KEY]) {\n throw new Error(`Input schema must have '${ORIGINAL_SNIPPET_KEY}' key set in translations`);\n }\n return new TranslatedSnippet(schema);\n }\n\n public static fromTypeScript(original: TypeScriptSnippet, didCompile?: boolean) {\n return new TranslatedSnippet({\n translations: {\n [ORIGINAL_SNIPPET_KEY]: { source: original.visibleSource, version: '0' },\n },\n didCompile: didCompile,\n location: original.location,\n fullSource: completeSource(original),\n });\n }\n\n public readonly snippet: TranslatedSnippetSchema;\n\n private readonly _snippet: Mutable<TranslatedSnippetSchema>;\n private _key?: string;\n\n private constructor(snippet: TranslatedSnippetSchema) {\n this._snippet = { ...snippet };\n this.snippet = this._snippet;\n }\n\n public get key() {\n if (this._key === undefined) {\n this._key = snippetKey(this.asTypescriptSnippet());\n }\n return this._key;\n }\n\n public get originalSource(): Translation {\n return {\n source: this.snippet.translations[ORIGINAL_SNIPPET_KEY].source,\n language: 'typescript',\n didCompile: this.snippet.didCompile,\n };\n }\n\n public addTranslation(language: TargetLanguage, translation: string, version: string): Translation {\n this.snippet.translations[language] = { source: translation, version };\n\n return {\n source: translation,\n language,\n didCompile: this.snippet.didCompile,\n };\n }\n\n public fqnsReferenced() {\n return this._snippet.fqnsReferenced ?? [];\n }\n\n public addSyntaxKindCounter(syntaxKindCounter: Record<string, number>) {\n if (!this._snippet.syntaxKindCounter) {\n this._snippet.syntaxKindCounter = {};\n }\n for (const [key, value] of Object.entries(syntaxKindCounter)) {\n const x = this._snippet.syntaxKindCounter[key] ?? 0;\n this._snippet.syntaxKindCounter[key] = value + x;\n }\n }\n\n public get languages(): TargetLanguage[] {\n return Object.keys(this.snippet.translations).filter((x) => x !== ORIGINAL_SNIPPET_KEY) as TargetLanguage[];\n }\n\n public get(language: TargetLanguage): Translation | undefined {\n const t = this.snippet.translations[language];\n return t && { source: t.source, language, didCompile: this.snippet.didCompile };\n }\n\n public mergeTranslations(other: TranslatedSnippet) {\n return new TranslatedSnippet({\n ...this.snippet,\n translations: { ...this.snippet.translations, ...other.snippet.translations },\n });\n }\n\n public withFingerprint(fp: string) {\n return new TranslatedSnippet({\n ...this.snippet,\n fqnsFingerprint: fp,\n });\n }\n\n public withLocation(location: SnippetLocation) {\n return new TranslatedSnippet({\n ...this.snippet,\n location,\n });\n }\n\n public toJSON() {\n return this._snippet;\n }\n\n private asTypescriptSnippet(): TypeScriptSnippet {\n return {\n visibleSource: this.snippet.translations[ORIGINAL_SNIPPET_KEY].source,\n location: this.snippet.location,\n };\n }\n}\n\nexport interface Translation {\n source: string;\n language: string;\n didCompile?: boolean;\n}\n\nasync function isGzipped(filename: string) {\n const openFile = await fs.open(filename, 'r');\n try {\n // Assumes that we can always read 3 bytes if there's that many in the file...\n const { bytesRead, buffer } = await openFile.read(Buffer.alloc(4), 0, 3, 0);\n return bytesRead >= 3 && buffer[0] === 0x1f && buffer[1] === 0x8b && buffer[2] === 0x08;\n } finally {\n await openFile.close();\n }\n}\n"]}
@@ -120,6 +120,11 @@ export declare class BatchSnippetTranslator {
120
120
  *
121
121
  * Reduce it down to only the information we need.
122
122
  */
123
+ export interface SnippetTimingInfo {
124
+ readonly name: string;
125
+ readonly snippetKey: string;
126
+ readonly durationMs: number;
127
+ }
123
128
  export interface RosettaDiagnostic {
124
129
  /**
125
130
  * If this is an error diagnostic or not
@@ -135,8 +140,18 @@ export interface RosettaDiagnostic {
135
140
  * Ends in a newline.
136
141
  */
137
142
  readonly formattedMessage: string;
143
+ /**
144
+ * Optional timing information for snippet translation
145
+ */
146
+ readonly timingInfo?: SnippetTimingInfo;
138
147
  }
139
148
  export declare function makeRosettaDiagnostic(isError: boolean, formattedMessage: string): RosettaDiagnostic;
149
+ export declare function makeTimingDiagnostic(snippetKey: string, name: string, durationMs: number): RosettaDiagnostic;
150
+ export declare function extractTimingInfo(diagnostics: readonly RosettaDiagnostic[]): {
151
+ timings: SnippetTimingInfo[];
152
+ diagnostics: RosettaDiagnostic[];
153
+ };
154
+ export declare function formatTimingTable(timings: SnippetTimingInfo[]): string;
140
155
  /**
141
156
  * Turn TypeScript diagnostics into Rosetta diagnostics
142
157
  */
package/lib/translate.js CHANGED
@@ -9,6 +9,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.BatchSnippetTranslator = exports.SnippetTranslator = exports.Translator = void 0;
10
10
  exports.translateTypeScript = translateTypeScript;
11
11
  exports.makeRosettaDiagnostic = makeRosettaDiagnostic;
12
+ exports.makeTimingDiagnostic = makeTimingDiagnostic;
13
+ exports.extractTimingInfo = extractTimingInfo;
14
+ exports.formatTimingTable = formatTimingTable;
12
15
  exports.rosettaDiagFromTypescript = rosettaDiagFromTypescript;
13
16
  const path = require("node:path");
14
17
  const node_util_1 = require("node:util");
@@ -21,7 +24,6 @@ const o_tree_1 = require("./o-tree");
21
24
  const renderer_1 = require("./renderer");
22
25
  const snippet_1 = require("./snippet");
23
26
  const submodule_reference_1 = require("./submodule-reference");
24
- const key_1 = require("./tablets/key");
25
27
  const schema_1 = require("./tablets/schema");
26
28
  const tablets_1 = require("./tablets/tablets");
27
29
  const syntax_kind_counter_1 = require("./typescript/syntax-kind-counter");
@@ -68,14 +70,8 @@ class Translator {
68
70
  * Translates a single snippet in its own TS context.
69
71
  */
70
72
  translate(snip, languages = Object.values(languages_1.TargetLanguage)) {
71
- const start = performance.now();
72
- logging.debug(`Translating ${(0, key_1.snippetKey)(snip)} ${(0, node_util_1.inspect)(snip.parameters ?? {})}`);
73
73
  const translator = this.translatorFor(snip);
74
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
75
  return translated;
80
76
  }
81
77
  /**
@@ -274,6 +270,49 @@ function filterVisibleDiagnostics(diags, visibleSpans) {
274
270
  function makeRosettaDiagnostic(isError, formattedMessage) {
275
271
  return { isError, formattedMessage, isFromStrictAssembly: false };
276
272
  }
273
+ function makeTimingDiagnostic(snippetKey, name, durationMs) {
274
+ return {
275
+ isError: false,
276
+ isFromStrictAssembly: false,
277
+ formattedMessage: '',
278
+ timingInfo: { snippetKey, name, durationMs },
279
+ };
280
+ }
281
+ function extractTimingInfo(diagnostics) {
282
+ const timings = [];
283
+ const regular = [];
284
+ for (const diag of diagnostics) {
285
+ if (diag.timingInfo) {
286
+ timings.push(diag.timingInfo);
287
+ }
288
+ else {
289
+ regular.push(diag);
290
+ }
291
+ }
292
+ return { timings, diagnostics: regular };
293
+ }
294
+ function formatTimingTable(timings) {
295
+ if (timings.length === 0) {
296
+ return '';
297
+ }
298
+ const totalTime = timings.reduce((sum, t) => sum + t.durationMs, 0);
299
+ const sorted = timings.sort((a, b) => b.durationMs - a.durationMs).slice(0, 10);
300
+ const lines = [
301
+ '',
302
+ '=== Top 10 Slowest Snippets ===',
303
+ 'Rank | Time (s) | % of Total | Snippet ',
304
+ '-----|----------|------------|--------------------------------',
305
+ ];
306
+ for (const [idx, timing] of sorted.entries()) {
307
+ const timeS = (timing.durationMs / 1000).toFixed(2).padStart(8);
308
+ const pct = ((timing.durationMs / totalTime) * 100).toFixed(1).padStart(9) + '%';
309
+ lines.push(`${(idx + 1).toString().padEnd(4)} | ${timeS} | ${pct} | ${timing.name}`);
310
+ }
311
+ lines.push('');
312
+ lines.push(`Total translation time: ${(totalTime / 1000).toFixed(2)}s`);
313
+ lines.push('');
314
+ return lines.join('\n');
315
+ }
277
316
  /**
278
317
  * Turn TypeScript diagnostics into Rosetta diagnostics
279
318
  */
@@ -1 +1 @@
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"]}
1
+ {"version":3,"file":"translate.js","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":";;;;;;;;;AAwBA,kDAeC;AAkYD,sDAEC;AAED,oDAOC;AAED,8CAgBC;AAED,8CA0BC;AAKD,8DAMC;AA7eD,kCAAkC;AAClC,yCAAoC;AACpC,iCAAiC;AAEjC,2CAA+D;AAC/D,qEAAwE;AACxE,iEAAgF;AAChF,qCAAqC;AACrC,qCAAsC;AACtC,yCAAyE;AACzE,uCAAiG;AACjG,+DAAkF;AAClF,6CAAwD;AACxD,+CAAsD;AACtD,0EAAqE;AACrE,0DAAyG;AACzG,8DAAmD;AACnD,iCAAmF;AAOnF,SAAgB,mBAAmB,CACjC,MAAY,EACZ,OAAwB,EACxB,UAAoC,EAAE;IAEtC,MAAM,UAAU,GAAG,IAAI,iBAAiB,CACtC,EAAE,aAAa,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE,EACjG,OAAO,CACR,CAAC;IACF,MAAM,UAAU,GAAG,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAEnD,OAAO;QACL,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,yBAAyB,CAAC;KACnE,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAa,UAAU;IAIrB,IAAW,WAAW;QACpB,OAAO,EAAE,CAAC,6BAA6B,CAAC,uBAAA,IAAI,+BAAa,CAAC,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAC5F,CAAC;IAED,YAAoC,0BAAmC;QAAnC,+BAA0B,GAA1B,0BAA0B,CAAS;QAPtD,aAAQ,GAAG,IAAI,gCAAkB,EAAE,CAAC;QACrD,kCAAgC,EAAE,EAAC;IAMuC,CAAC;IAE3E;;;;;OAKG;IACI,aAAa,CAAC,OAA0B;QAC7C,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC,OAAO,EAAE;YAChD,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,0BAA0B,EAAE,IAAI,CAAC,0BAA0B;SAC5D,CAAC,CAAC;QACH,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,IAAuB,EAAE,YAAuC,MAAM,CAAC,MAAM,CAAC,0BAAc,CAAC;QAC5G,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QACtE,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACI,iBAAiB,CACtB,QAA6B,EAC7B,YAAuC,MAAM,CAAC,MAAM,CAAC,0BAAc,CAAC;QAEpE,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,WAAW,CAAC,CAAC;QAElE,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAErD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAC3C,OAAO,CAAC,KAAK,CACX,mBAAmB,IAAA,mBAAO,EAAC;YACzB,QAAQ,EAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;SAC7C,CAAC,EAAE,CACL,CAAC;QAEF,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,cAAc,CACpB,QAA6B,EAC7B,YAAuC,MAAM,CAAC,MAAM,CAAC,0BAAc,CAAC;QAEpE,MAAM,kBAAkB,GAAwB,EAAE,CAAC;QAEnD,MAAM,eAAe,GAAG,IAAI,sBAAsB,CAAC,QAAQ,EAAE;YAC3D,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,0BAA0B,EAAE,IAAI,CAAC,0BAA0B;SAC5D,CAAC,CAAC;QAEH,KAAK,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,eAAe,EAAE,CAAC;YACpD,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;QACjF,CAAC;QAED,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAEO,gBAAgB,CACtB,OAA0B,EAC1B,UAA8B,EAC9B,SAAoC;QAEpC,MAAM,YAAY,GAAG,IAAA,aAAM,EACzB,SAAS,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YACrC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvC,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,wBAAwB,GAAG,4BAAgB,CAAC,IAAI,CAAC,CAAC;YACxD,MAAM,UAAU,GAAG,UAAU,CAAC,WAAW,CAAC,wBAAwB,CAAC,aAAa,EAAE,CAAC,CAAC;YACpF,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,wBAAwB,CAAC,OAAO,EAAE,CAAU,CAAC,CAAC;QAC9F,CAAC,CAAC,CACH,CAAC;QAEF,IAAI,OAAO,CAAC,UAAU,EAAE,OAAO,KAAK,SAAS,EAAE,CAAC;YAC9C,uBAAA,IAAI,+BAAa,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,2BAAiB,CAAC,UAAU,CAAC;YAClC,YAAY,EAAE;gBACZ,GAAG,YAAY;gBACf,CAAC,6BAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,aAAa,EAAE,OAAO,EAAE,GAAG,EAAE;aACxE;YACD,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,UAAU,EAAE,UAAU,CAAC,sBAAsB;YAC7C,cAAc,EAAE,UAAU,CAAC,cAAc,EAAE;YAC3C,UAAU,EAAE,IAAA,wBAAc,EAAC,OAAO,CAAC;YACnC,iBAAiB,EAAE,UAAU,CAAC,iBAAiB,EAAE;SAClD,CAAC,CAAC;IACL,CAAC;CACF;AAzGD,gCAyGC;;AA2BD;;;;GAIG;AACH,MAAM,yBAAyB;IAQ7B,YACE,OAA0B,EACT,WAA8B,EAC9B,OAAiC;QADjC,gBAAW,GAAX,WAAW,CAAmB;QAC9B,YAAO,GAAP,OAAO,CAA0B;QAVpC,yBAAoB,GAAoB,EAAE,CAAC;QAC3C,uBAAkB,GAAoB,EAAE,CAAC;QAWvD,iDAAiD;QACjD,oEAAoE;QACpE,IAAI,CAAC,YAAY,GAAG,qBAAK,CAAC,sBAAsB,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAE5E,gDAAgD;QAChD,IAAI,CAAC,mBAAmB,GAAG,wCAAkB,CAAC,YAAY,CACxD,WAAW,CAAC,QAAQ,EACpB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,EAAE,CAC1C,CAAC;QAEF,yDAAyD;QACzD,wEAAwE;QACxE,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,0BAA0B,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;QACvF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;YACzC,MAAM,WAAW,GAAG;gBAClB,GAAG,aAAa,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE;gBAChD,GAAG,aAAa,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;gBAC5E,GAAG,aAAa,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;gBAC9E,GAAG,aAAa,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;aAC5E,CAAC;YAEF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,uEAAuE;gBACvE,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;oBAC/B,IAAA,+BAAwB,EAAC,IAAI,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;YACD,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,IAAW,sBAAsB;QAC/B,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,CAAC;IAEM,WAAW,CAAC,OAAwB;QACzC,MAAM,SAAS,GAAG,IAAI,sBAAW,CAC/B,IAAI,CAAC,WAAW,CAAC,QAAQ,EACzB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,EAAE,EACzC,OAAO,EACP,IAAI,CAAC,OAAO;QACZ,sFAAsF;QACtF,IAAA,mDAAiC,EAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAC3F,CAAC;QACF,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,wBAAwB,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACtG,OAAO,IAAA,mBAAU,EAAC,SAAS,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IACpG,CAAC;IAEM,iBAAiB;QACtB,MAAM,WAAW,GAAG,IAAI,uCAAiB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7D,OAAO,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC3D,CAAC;IAEM,cAAc;QACnB,MAAM,OAAO,GAAG,IAAI,2CAAuB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,IAAI,sBAAW,CAC/B,IAAI,CAAC,WAAW,CAAC,QAAQ,EACzB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,EAAE,EACzC,OAAO,EACP,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,mBAAmB,CACzB,CAAC;QACF,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC7C,OAAO,OAAO,CAAC,cAAc,EAAE,CAAC;IAClC,CAAC;IAED,IAAW,WAAW;QACpB,OAAO,EAAE,CAAC,6BAA6B,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACrG,CAAC;CACF;AAED;;GAEG;AACH,MAAa,iBAAkB,SAAQ,yBAAyB;IAC9D,YAAmB,OAA0B,EAAE,UAAoC,EAAE;QACnF,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,gCAAkB,EAAE,CAAC;QAC9D,MAAM,MAAM,GAAG,IAAA,wBAAc,EAAC,OAAO,CAAC,CAAC;QACvC,MAAM,oBAAoB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,2BAAiB,CAAC,sBAAsB,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAC7G,MAAM,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAC/C;YACE;gBACE,QAAQ,EAAE,aAAa,CAAC,IAAA,wBAAc,EAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACzD,QAAQ,EAAE,MAAM;aACjB;SACF,EACD,oBAAoB,CACrB,CAAC;QAEF,KAAK,CACH,OAAO,EACP;YACE,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,QAAQ,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;SACnC,EACD,OAAO,CACR,CAAC;IACJ,CAAC;CACF;AAxBD,8CAwBC;AAcD;;GAEG;AACH,MAAa,sBAAsB;IAGjC,YACmB,QAA6B,EAC7B,UAAyC,EAAE;QAD3C,aAAQ,GAAR,QAAQ,CAAqB;QAC7B,YAAO,GAAP,OAAO,CAAoC;QAE5D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,gCAAkB,EAAE,CAAC;QAC9D,MAAM,UAAU,GAAG,OAAO,CAAC,oBAAoB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAEjE,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YACvC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,2BAAiB,CAAC,sBAAsB,CAAC,CAAC;YAClF,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAA,wBAAc,EAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;YAEjE,OAAO;gBACL,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ;gBAC5F,QAAQ,EAAE,IAAA,wBAAc,EAAC,OAAO,CAAC;aAClC,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACxE,CAAC;IAED,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;QAChB,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAEjD,MAAM,UAAU,GAAuB,IAAI,yBAAyB,CAClE,OAAO,EACP;gBACE,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO;gBACjC,QAAQ;aACT,EACD,IAAI,CAAC,OAAO,CACb,CAAC;YAEF,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;CACF;AAtCD,wDAsCC;AAED;;;;;GAKG;AACH,SAAS,aAAa,CAAyB,IAAkC;IAC/E,OAAO,CAAC,GAAG,IAAO,EAAE,EAAE;QACpB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,MAAM,yBAAyB,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;YAExE,IAAI,CAAC,yBAAyB,EAAE,CAAC;gBAC/B,OAAO,CAAC,KAAK,CAAC,qBAAqB,IAAI,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC,CAAC;YAC1D,CAAC;YAED,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,wBAAwB,CAAC,KAA+B,EAAE,YAAmB;IACpF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,IAAI,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AACxH,CAAC;AAyCD,SAAgB,qBAAqB,CAAC,OAAgB,EAAE,gBAAwB;IAC9E,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;AACpE,CAAC;AAED,SAAgB,oBAAoB,CAAC,UAAkB,EAAE,IAAY,EAAE,UAAkB;IACvF,OAAO;QACL,OAAO,EAAE,KAAK;QACd,oBAAoB,EAAE,KAAK;QAC3B,gBAAgB,EAAE,EAAE;QACpB,UAAU,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE;KAC7C,CAAC;AACJ,CAAC;AAED,SAAgB,iBAAiB,CAAC,WAAyC;IAIzE,MAAM,OAAO,GAAwB,EAAE,CAAC;IACxC,MAAM,OAAO,GAAwB,EAAE,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AAC3C,CAAC;AAED,SAAgB,iBAAiB,CAAC,OAA4B;IAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEhF,MAAM,KAAK,GAAG;QACZ,EAAE;QACF,iCAAiC;QACjC,yCAAyC;QACzC,gEAAgE;KACjE,CAAC;IAEF,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QACjF,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,SAAgB,yBAAyB,CAAC,IAAmB;IAC3D,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,QAAQ,KAAK,EAAE,CAAC,kBAAkB,CAAC,KAAK;QACtD,oBAAoB,EAAE,IAAA,wBAAiB,EAAC,IAAI,CAAC;QAC7C,gBAAgB,EAAE,EAAE,CAAC,oCAAoC,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;KAC7E,CAAC;AACJ,CAAC;AAED,MAAM,SAAS,GAAG;IAChB,mBAAmB;QACjB,OAAO,GAAG,CAAC;IACb,CAAC;IACD,oBAAoB,CAAC,QAAgB;QACnC,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,UAAU;QACR,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC;AAEF;;;GAGG;AACH,SAAS,aAAa,CAAC,CAAS;IAC9B,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC","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 { 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 translator = this.translatorFor(snip);\n const translated = this.translateSnippet(snip, translator, languages);\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 SnippetTimingInfo {\n readonly name: string;\n readonly snippetKey: string;\n readonly durationMs: number;\n}\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 /**\n * Optional timing information for snippet translation\n */\n readonly timingInfo?: SnippetTimingInfo;\n}\n\nexport function makeRosettaDiagnostic(isError: boolean, formattedMessage: string): RosettaDiagnostic {\n return { isError, formattedMessage, isFromStrictAssembly: false };\n}\n\nexport function makeTimingDiagnostic(snippetKey: string, name: string, durationMs: number): RosettaDiagnostic {\n return {\n isError: false,\n isFromStrictAssembly: false,\n formattedMessage: '',\n timingInfo: { snippetKey, name, durationMs },\n };\n}\n\nexport function extractTimingInfo(diagnostics: readonly RosettaDiagnostic[]): {\n timings: SnippetTimingInfo[];\n diagnostics: RosettaDiagnostic[];\n} {\n const timings: SnippetTimingInfo[] = [];\n const regular: RosettaDiagnostic[] = [];\n\n for (const diag of diagnostics) {\n if (diag.timingInfo) {\n timings.push(diag.timingInfo);\n } else {\n regular.push(diag);\n }\n }\n\n return { timings, diagnostics: regular };\n}\n\nexport function formatTimingTable(timings: SnippetTimingInfo[]): string {\n if (timings.length === 0) {\n return '';\n }\n\n const totalTime = timings.reduce((sum, t) => sum + t.durationMs, 0);\n const sorted = timings.sort((a, b) => b.durationMs - a.durationMs).slice(0, 10);\n\n const lines = [\n '',\n '=== Top 10 Slowest Snippets ===',\n 'Rank | Time (s) | % of Total | Snippet ',\n '-----|----------|------------|--------------------------------',\n ];\n\n for (const [idx, timing] of sorted.entries()) {\n const timeS = (timing.durationMs / 1000).toFixed(2).padStart(8);\n const pct = ((timing.durationMs / totalTime) * 100).toFixed(1).padStart(9) + '%';\n lines.push(`${(idx + 1).toString().padEnd(4)} | ${timeS} | ${pct} | ${timing.name}`);\n }\n\n lines.push('');\n lines.push(`Total translation time: ${(totalTime / 1000).toFixed(2)}s`);\n lines.push('');\n\n return lines.join('\\n');\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,6 +1,6 @@
1
1
  import { TypeScriptSnippet } from './snippet';
2
2
  import { TranslatedSnippet } from './tablets/tablets';
3
- import { RosettaDiagnostic } from './translate';
3
+ import { RosettaDiagnostic, SnippetTimingInfo } from './translate';
4
4
  /**
5
5
  * Divide the work evenly over all processors by running 'translate_all_worker' in Worker Threads, then combine results
6
6
  *
@@ -15,5 +15,6 @@ export declare function translateAll(snippets: TypeScriptSnippet[], includeCompi
15
15
  export interface TranslateAllResult {
16
16
  translatedSnippets: TranslatedSnippet[];
17
17
  diagnostics: RosettaDiagnostic[];
18
+ timings?: SnippetTimingInfo[];
18
19
  }
19
20
  //# sourceMappingURL=translate_all.d.ts.map
@@ -6,6 +6,7 @@ const path = require("node:path");
6
6
  const workerpool = require("workerpool");
7
7
  const logging = require("./logging");
8
8
  const tablets_1 = require("./tablets/tablets");
9
+ const translate_1 = require("./translate");
9
10
  /**
10
11
  * Divide the work evenly over all processors by running 'translate_all_worker' in Worker Threads, then combine results
11
12
  *
@@ -34,14 +35,20 @@ async function translateAll(snippets, includeCompilerDiagnostics, batchSize) {
34
35
  const shouldBatchCompilation = batchSize != null;
35
36
  const requests = batchSnippets(snippetArr, includeCompilerDiagnostics, batchSize, shouldBatchCompilation);
36
37
  const responses = await Promise.all(requests.map((request) => pool.exec('translateBatch', [request])));
37
- const diagnostics = new Array();
38
+ const allDiagnostics = new Array();
38
39
  const translatedSnippets = new Array();
39
40
  // Combine results
40
41
  for (const response of responses) {
41
- diagnostics.push(...response.diagnostics);
42
+ allDiagnostics.push(...response.diagnostics);
42
43
  translatedSnippets.push(...response.translatedSchemas.map(tablets_1.TranslatedSnippet.fromSchema));
43
44
  }
44
- return { diagnostics, translatedSnippets };
45
+ // Extract timing info if enabled
46
+ const { timings, diagnostics } = (0, translate_1.extractTimingInfo)(allDiagnostics);
47
+ return {
48
+ diagnostics,
49
+ translatedSnippets,
50
+ timings: process.env.TIMING === '1' ? timings : undefined,
51
+ };
45
52
  }
46
53
  finally {
47
54
  // Not waiting on purpose