jsii-rosetta 5.9.21 → 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.
- package/lib/commands/extract.js +2 -2
- package/lib/commands/extract.js.map +1 -1
- package/lib/commands/infuse.js +3 -3
- package/lib/commands/infuse.js.map +1 -1
- package/lib/commands/trim-cache.js +1 -1
- package/lib/commands/trim-cache.js.map +1 -1
- package/lib/rosetta-reader.js +2 -2
- package/lib/rosetta-reader.js.map +1 -1
- package/lib/rosetta-translator.js +4 -4
- package/lib/rosetta-translator.js.map +1 -1
- package/lib/tablets/tablets.d.ts +14 -8
- package/lib/tablets/tablets.js +23 -13
- package/lib/tablets/tablets.js.map +1 -1
- package/package.json +1 -1
package/lib/commands/extract.js
CHANGED
|
@@ -93,7 +93,7 @@ async function extractSnippets(assemblyLocations, options = {}) {
|
|
|
93
93
|
logging.debug(`Writing ${snips.length} translations to ${asmTabletFile}`);
|
|
94
94
|
const translations = snips.map(({ key }) => translator.tablet.tryGetSnippet(key)).filter(util_1.isDefined);
|
|
95
95
|
const asmTablet = new tablets_1.LanguageTablet();
|
|
96
|
-
asmTablet.
|
|
96
|
+
asmTablet.addTranslations(...translations);
|
|
97
97
|
await asmTablet.save(asmTabletFile, compressedTablet);
|
|
98
98
|
}));
|
|
99
99
|
}
|
|
@@ -103,7 +103,7 @@ async function extractSnippets(assemblyLocations, options = {}) {
|
|
|
103
103
|
const output = options.trimCache
|
|
104
104
|
? new tablets_1.LanguageTablet()
|
|
105
105
|
: await tablets_1.LanguageTablet.fromOptionalFile(options.cacheToFile);
|
|
106
|
-
output.
|
|
106
|
+
output.addSnippetsFromTablets(translator.tablet);
|
|
107
107
|
await output.save(options.cacheToFile, options.compressCacheToFile);
|
|
108
108
|
}
|
|
109
109
|
return { diagnostics, tablet: translator.tablet, timings };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'node:path';\n\nimport { infuse } from './infuse';\nimport {\n loadAssemblies,\n allTypeScriptSnippets,\n loadAllDefaultTablets,\n compressedTabletExists,\n} from '../jsii/assemblies';\nimport * as logging from '../logging';\nimport { RosettaTranslator, RosettaTranslatorOptions } from '../rosetta-translator';\nimport { TypeScriptSnippet, SnippetParameters } from '../snippet';\nimport { snippetKey } from '../tablets/key';\nimport { LanguageTablet, DEFAULT_TABLET_NAME, DEFAULT_TABLET_NAME_COMPRESSED } from '../tablets/tablets';\nimport { RosettaDiagnostic, SnippetTimingInfo } from '../translate';\nimport { groupBy, isDefined } from '../util';\n\nexport interface ExtractResult {\n diagnostics: RosettaDiagnostic[];\n tablet: LanguageTablet;\n timings?: SnippetTimingInfo[];\n}\n\nexport interface ExtractOptions {\n readonly includeCompilerDiagnostics?: boolean;\n readonly validateAssemblies?: boolean;\n readonly only?: string[];\n\n /**\n * A tablet file to be loaded and used as a source for caching\n */\n readonly cacheFromFile?: string;\n\n /**\n * A tablet file to append translated snippets to\n */\n readonly cacheToFile?: string;\n\n /**\n * Trim cache to only contain translations found in the current assemblies\n *\n * @default false\n */\n readonly trimCache?: boolean;\n\n /**\n * Write translations to implicit tablets (`.jsii.tabl.json`)\n *\n * @default true\n */\n readonly writeToImplicitTablets?: boolean;\n\n /**\n * What directory to compile the samples in\n *\n * @default - Rosetta manages the compilation directory\n * @deprecated Samples declare their own dependencies instead\n */\n readonly compilationDirectory?: string;\n\n /**\n * Make a translator (just for testing)\n */\n readonly translatorFactory?: (opts: RosettaTranslatorOptions) => RosettaTranslator;\n\n /**\n * Turn on 'loose mode' or not\n *\n * Loose mode ignores failures during fixturizing, and undoes 'strict mode' for\n * diagnostics.\n *\n * @default false\n */\n readonly loose?: boolean;\n\n /**\n * Accept dirty translations from the cache\n *\n * @default false\n */\n readonly allowDirtyTranslations?: boolean;\n\n /**\n * Compress the implicit tablet files.\n *\n * @default - preserves the original compression status of each individual implicit tablet file.\n */\n readonly compressTablet?: boolean;\n\n /**\n * Compress the cacheToFile tablet.\n *\n * @default false\n */\n readonly compressCacheToFile?: boolean;\n\n /**\n * Cleanup temporary directories\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\nexport async function extractAndInfuse(assemblyLocations: string[], options: ExtractOptions): Promise<ExtractResult> {\n const result = await extractSnippets(assemblyLocations, options);\n await infuse(assemblyLocations, {\n cacheFromFile: options.cacheFromFile,\n cacheToFile: options.cacheToFile,\n compressCacheToFile: options.compressCacheToFile,\n });\n return result;\n}\n\n/**\n * Extract all samples from the given assemblies into a tablet\n */\nexport async function extractSnippets(\n assemblyLocations: readonly string[],\n options: ExtractOptions = {},\n): Promise<ExtractResult> {\n const only = options.only ?? [];\n\n logging.info(`Loading ${assemblyLocations.length} assemblies`);\n const assemblies = loadAssemblies(assemblyLocations, options.validateAssemblies ?? false);\n\n let snippets = Array.from(await allTypeScriptSnippets(assemblies, options.loose));\n if (only.length > 0) {\n snippets = filterSnippets(snippets, only);\n }\n\n // Map every assembly to a list of snippets, so that we know what implicit\n // tablet to write the translations to later on.\n const snippetsPerAssembly = groupBy(\n snippets.map((s) => ({ key: snippetKey(s), location: projectDirectory(s) })),\n (x) => x.location,\n );\n\n const translatorOptions: RosettaTranslatorOptions = {\n includeCompilerDiagnostics: options.includeCompilerDiagnostics ?? false,\n assemblies: assemblies.map((a) => a.assembly),\n allowDirtyTranslations: options.allowDirtyTranslations,\n };\n\n const translator = options.translatorFactory\n ? options.translatorFactory(translatorOptions)\n : new RosettaTranslator(translatorOptions);\n\n // Prime the snippet cache with:\n // - Cache source file\n // - Default tablets found next to each assembly\n if (options.cacheFromFile) {\n await translator.addToCache(options.cacheFromFile);\n }\n translator.addTabletsToCache(...Object.values(await loadAllDefaultTablets(assemblies)));\n\n if (translator.hasCache()) {\n const cache = translator.readFromCache(snippets, true, options.includeCompilerDiagnostics);\n logging.info(`Reused ${cache.dirtyCount === 0 ? 'all ' : ''}${cache.translations.length} translations from cache`);\n if (cache.dirtyCount) {\n const dirt = {\n 'non-compiling': cache.dirtyDidntCompile,\n 'changed sources': cache.dirtySourceCount,\n 'changed translator version': cache.dirtyTranslatorCount,\n 'changed types': cache.dirtyTypesCount,\n };\n logging.info(\n `Dropped ${cache.dirtyCount} translations (${Object.entries(dirt)\n .filter(([_, count]) => !!count)\n .map(([desc, count]) => `${count} ${desc}`)\n .join(', ')})`,\n );\n }\n\n snippets = cache.remaining;\n }\n\n const diagnostics = [];\n const timings: SnippetTimingInfo[] = [];\n if (snippets.length > 0) {\n logging.info('Translating');\n const startTime = Date.now();\n\n const result = await translator.translateAll(snippets, {\n compilationDirectory: options.compilationDirectory,\n cleanup: options.cleanup,\n batchSize: options.batchSize,\n });\n\n const delta = (Date.now() - startTime) / 1000;\n logging.info(\n `Translated ${snippets.length} snippets in ${delta} seconds (${(delta / snippets.length).toPrecision(\n 3,\n )}s/snippet)`,\n );\n diagnostics.push(...result.diagnostics);\n timings.push(...(result.timings ?? []));\n } else {\n logging.info('Nothing left to translate');\n }\n\n // Save to individual tablet files\n if (options.writeToImplicitTablets ?? true) {\n await Promise.all(\n Object.entries(snippetsPerAssembly).map(async ([location, snips]) => {\n // Compress the implicit tablet if explicitly asked to, otherwise compress only if the original tablet was compressed.\n const compressedTablet = options.compressTablet ?? compressedTabletExists(location);\n\n const asmTabletFile = path.join(\n location,\n compressedTablet ? DEFAULT_TABLET_NAME_COMPRESSED : DEFAULT_TABLET_NAME,\n );\n logging.debug(`Writing ${snips.length} translations to ${asmTabletFile}`);\n const translations = snips.map(({ key }) => translator.tablet.tryGetSnippet(key)).filter(isDefined);\n\n const asmTablet = new LanguageTablet();\n asmTablet.addSnippets(...translations);\n await asmTablet.save(asmTabletFile, compressedTablet);\n }),\n );\n }\n\n // optionally append to the output file\n if (options.cacheToFile) {\n logging.info(`Adding translations to ${options.cacheToFile}`);\n const output = options.trimCache\n ? new LanguageTablet()\n : await LanguageTablet.fromOptionalFile(options.cacheToFile);\n output.addTablets(translator.tablet);\n await output.save(options.cacheToFile, options.compressCacheToFile);\n }\n\n return { diagnostics, tablet: translator.tablet, timings };\n}\n\n/**\n * Only yield the snippets whose id exists in a whitelist\n */\nfunction filterSnippets(ts: TypeScriptSnippet[], includeIds: string[]) {\n return ts.filter((t) => includeIds.includes(snippetKey(t)));\n}\n\nfunction projectDirectory(ts: TypeScriptSnippet) {\n const dir = ts.parameters?.[SnippetParameters.$PROJECT_DIRECTORY];\n if (!dir) {\n throw new Error(`Snippet does not have associated project directory: ${JSON.stringify(ts.location)}`);\n }\n return dir;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'node:path';\n\nimport { infuse } from './infuse';\nimport {\n loadAssemblies,\n allTypeScriptSnippets,\n loadAllDefaultTablets,\n compressedTabletExists,\n} from '../jsii/assemblies';\nimport * as logging from '../logging';\nimport { RosettaTranslator, RosettaTranslatorOptions } from '../rosetta-translator';\nimport { TypeScriptSnippet, SnippetParameters } from '../snippet';\nimport { snippetKey } from '../tablets/key';\nimport { LanguageTablet, DEFAULT_TABLET_NAME, DEFAULT_TABLET_NAME_COMPRESSED } from '../tablets/tablets';\nimport { RosettaDiagnostic, SnippetTimingInfo } from '../translate';\nimport { groupBy, isDefined } from '../util';\n\nexport interface ExtractResult {\n diagnostics: RosettaDiagnostic[];\n tablet: LanguageTablet;\n timings?: SnippetTimingInfo[];\n}\n\nexport interface ExtractOptions {\n readonly includeCompilerDiagnostics?: boolean;\n readonly validateAssemblies?: boolean;\n readonly only?: string[];\n\n /**\n * A tablet file to be loaded and used as a source for caching\n */\n readonly cacheFromFile?: string;\n\n /**\n * A tablet file to append translated snippets to\n */\n readonly cacheToFile?: string;\n\n /**\n * Trim cache to only contain translations found in the current assemblies\n *\n * @default false\n */\n readonly trimCache?: boolean;\n\n /**\n * Write translations to implicit tablets (`.jsii.tabl.json`)\n *\n * @default true\n */\n readonly writeToImplicitTablets?: boolean;\n\n /**\n * What directory to compile the samples in\n *\n * @default - Rosetta manages the compilation directory\n * @deprecated Samples declare their own dependencies instead\n */\n readonly compilationDirectory?: string;\n\n /**\n * Make a translator (just for testing)\n */\n readonly translatorFactory?: (opts: RosettaTranslatorOptions) => RosettaTranslator;\n\n /**\n * Turn on 'loose mode' or not\n *\n * Loose mode ignores failures during fixturizing, and undoes 'strict mode' for\n * diagnostics.\n *\n * @default false\n */\n readonly loose?: boolean;\n\n /**\n * Accept dirty translations from the cache\n *\n * @default false\n */\n readonly allowDirtyTranslations?: boolean;\n\n /**\n * Compress the implicit tablet files.\n *\n * @default - preserves the original compression status of each individual implicit tablet file.\n */\n readonly compressTablet?: boolean;\n\n /**\n * Compress the cacheToFile tablet.\n *\n * @default false\n */\n readonly compressCacheToFile?: boolean;\n\n /**\n * Cleanup temporary directories\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\nexport async function extractAndInfuse(assemblyLocations: string[], options: ExtractOptions): Promise<ExtractResult> {\n const result = await extractSnippets(assemblyLocations, options);\n await infuse(assemblyLocations, {\n cacheFromFile: options.cacheFromFile,\n cacheToFile: options.cacheToFile,\n compressCacheToFile: options.compressCacheToFile,\n });\n return result;\n}\n\n/**\n * Extract all samples from the given assemblies into a tablet\n */\nexport async function extractSnippets(\n assemblyLocations: readonly string[],\n options: ExtractOptions = {},\n): Promise<ExtractResult> {\n const only = options.only ?? [];\n\n logging.info(`Loading ${assemblyLocations.length} assemblies`);\n const assemblies = loadAssemblies(assemblyLocations, options.validateAssemblies ?? false);\n\n let snippets = Array.from(await allTypeScriptSnippets(assemblies, options.loose));\n if (only.length > 0) {\n snippets = filterSnippets(snippets, only);\n }\n\n // Map every assembly to a list of snippets, so that we know what implicit\n // tablet to write the translations to later on.\n const snippetsPerAssembly = groupBy(\n snippets.map((s) => ({ key: snippetKey(s), location: projectDirectory(s) })),\n (x) => x.location,\n );\n\n const translatorOptions: RosettaTranslatorOptions = {\n includeCompilerDiagnostics: options.includeCompilerDiagnostics ?? false,\n assemblies: assemblies.map((a) => a.assembly),\n allowDirtyTranslations: options.allowDirtyTranslations,\n };\n\n const translator = options.translatorFactory\n ? options.translatorFactory(translatorOptions)\n : new RosettaTranslator(translatorOptions);\n\n // Prime the snippet cache with:\n // - Cache source file\n // - Default tablets found next to each assembly\n if (options.cacheFromFile) {\n await translator.addToCache(options.cacheFromFile);\n }\n translator.addTabletsToCache(...Object.values(await loadAllDefaultTablets(assemblies)));\n\n if (translator.hasCache()) {\n const cache = translator.readFromCache(snippets, true, options.includeCompilerDiagnostics);\n logging.info(`Reused ${cache.dirtyCount === 0 ? 'all ' : ''}${cache.translations.length} translations from cache`);\n if (cache.dirtyCount) {\n const dirt = {\n 'non-compiling': cache.dirtyDidntCompile,\n 'changed sources': cache.dirtySourceCount,\n 'changed translator version': cache.dirtyTranslatorCount,\n 'changed types': cache.dirtyTypesCount,\n };\n logging.info(\n `Dropped ${cache.dirtyCount} translations (${Object.entries(dirt)\n .filter(([_, count]) => !!count)\n .map(([desc, count]) => `${count} ${desc}`)\n .join(', ')})`,\n );\n }\n\n snippets = cache.remaining;\n }\n\n const diagnostics = [];\n const timings: SnippetTimingInfo[] = [];\n if (snippets.length > 0) {\n logging.info('Translating');\n const startTime = Date.now();\n\n const result = await translator.translateAll(snippets, {\n compilationDirectory: options.compilationDirectory,\n cleanup: options.cleanup,\n batchSize: options.batchSize,\n });\n\n const delta = (Date.now() - startTime) / 1000;\n logging.info(\n `Translated ${snippets.length} snippets in ${delta} seconds (${(delta / snippets.length).toPrecision(\n 3,\n )}s/snippet)`,\n );\n diagnostics.push(...result.diagnostics);\n timings.push(...(result.timings ?? []));\n } else {\n logging.info('Nothing left to translate');\n }\n\n // Save to individual tablet files\n if (options.writeToImplicitTablets ?? true) {\n await Promise.all(\n Object.entries(snippetsPerAssembly).map(async ([location, snips]) => {\n // Compress the implicit tablet if explicitly asked to, otherwise compress only if the original tablet was compressed.\n const compressedTablet = options.compressTablet ?? compressedTabletExists(location);\n\n const asmTabletFile = path.join(\n location,\n compressedTablet ? DEFAULT_TABLET_NAME_COMPRESSED : DEFAULT_TABLET_NAME,\n );\n logging.debug(`Writing ${snips.length} translations to ${asmTabletFile}`);\n const translations = snips.map(({ key }) => translator.tablet.tryGetSnippet(key)).filter(isDefined);\n\n const asmTablet = new LanguageTablet();\n asmTablet.addTranslations(...translations);\n await asmTablet.save(asmTabletFile, compressedTablet);\n }),\n );\n }\n\n // optionally append to the output file\n if (options.cacheToFile) {\n logging.info(`Adding translations to ${options.cacheToFile}`);\n const output = options.trimCache\n ? new LanguageTablet()\n : await LanguageTablet.fromOptionalFile(options.cacheToFile);\n output.addSnippetsFromTablets(translator.tablet);\n await output.save(options.cacheToFile, options.compressCacheToFile);\n }\n\n return { diagnostics, tablet: translator.tablet, timings };\n}\n\n/**\n * Only yield the snippets whose id exists in a whitelist\n */\nfunction filterSnippets(ts: TypeScriptSnippet[], includeIds: string[]) {\n return ts.filter((t) => includeIds.includes(snippetKey(t)));\n}\n\nfunction projectDirectory(ts: TypeScriptSnippet) {\n const dir = ts.parameters?.[SnippetParameters.$PROJECT_DIRECTORY];\n if (!dir) {\n throw new Error(`Snippet does not have associated project directory: ${JSON.stringify(ts.location)}`);\n }\n return dir;\n}\n"]}
|
package/lib/commands/infuse.js
CHANGED
|
@@ -41,9 +41,9 @@ async function infuse(assemblyLocations, options) {
|
|
|
41
41
|
const defaultTablets = await (0, assemblies_1.loadAllDefaultTablets)(assemblies);
|
|
42
42
|
const availableTranslations = new tablets_1.LanguageTablet();
|
|
43
43
|
if (options?.cacheFromFile) {
|
|
44
|
-
availableTranslations.
|
|
44
|
+
availableTranslations.addTranslationsFromTablet(await tablets_1.LanguageTablet.fromOptionalFile(options.cacheFromFile));
|
|
45
45
|
}
|
|
46
|
-
availableTranslations.
|
|
46
|
+
availableTranslations.addTranslationsFromTablets(...Object.values(defaultTablets));
|
|
47
47
|
const { translationsByFqn, originalsByKey } = await availableSnippetsPerFqn(assemblies, availableTranslations);
|
|
48
48
|
const additionalOutputTablet = options?.cacheToFile
|
|
49
49
|
? await tablets_1.LanguageTablet.fromOptionalFile(options?.cacheToFile)
|
|
@@ -165,7 +165,7 @@ function insertExample(example, original, type, tablets) {
|
|
|
165
165
|
};
|
|
166
166
|
}
|
|
167
167
|
for (const tablet of tablets) {
|
|
168
|
-
tablet.
|
|
168
|
+
tablet.addTranslations(example.withLocation({
|
|
169
169
|
api: { api: 'type', fqn: type.fqn },
|
|
170
170
|
field: { field: 'example' },
|
|
171
171
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"infuse.js","sourceRoot":"","sources":["../../src/commands/infuse.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as spec from '@jsii/spec';\nimport { replaceAssembly } from '@jsii/spec';\n\nimport { loadAssemblies, loadAllDefaultTablets, LoadedAssembly, allTypeScriptSnippets } from '../jsii/assemblies';\nimport { renderMetadataline, TypeScriptSnippet } from '../snippet';\nimport { SnippetSelector, mean, meanLength, shortest, longest } from '../snippet-selectors';\nimport { snippetKey } from '../tablets/key';\nimport {\n LanguageTablet,\n TranslatedSnippet,\n DEFAULT_TABLET_NAME,\n DEFAULT_TABLET_NAME_COMPRESSED,\n} from '../tablets/tablets';\nimport { isDefined, mkDict, indexBy } from '../util';\n\nexport interface InfuseResult {\n readonly coverageResults: Record<string, InfuseTypes>;\n}\n\nexport interface InfuseTypes {\n readonly types: number;\n readonly typesWithInsertedExamples: number;\n}\n\nexport interface InfuseOptions {\n readonly logFile?: string;\n\n /**\n * Where to read additional translations\n */\n readonly cacheFromFile?: string;\n\n /**\n * In addition to the implicit tablets, also write all added examples to this additional output tablet\n */\n readonly cacheToFile?: string;\n\n /**\n * Compress the cacheToFile\n */\n readonly compressCacheToFile?: boolean;\n}\n\nexport const DEFAULT_INFUSION_RESULTS_NAME = 'infusion-results.html';\n\nconst ADDITIONAL_SELECTORS: Record<string, SnippetSelector> = { meanLength, shortest, longest };\n\nclass DefaultRecord<A> {\n public readonly index: Record<string, A[]> = {};\n\n public add(key: string, value: A) {\n if (!this.index[key]) {\n this.index[key] = [];\n }\n this.index[key].push(value);\n }\n}\n\n/**\n * Infuse will analyze the snippets in a set of tablets, and update the assembly to add\n * examples to types that don't have any yet, based on snippets that use the given type.\n */\nexport async function infuse(assemblyLocations: string[], options?: InfuseOptions): Promise<InfuseResult> {\n let stream: fs.WriteStream | undefined = undefined;\n if (options?.logFile) {\n // Create stream for html file and insert some styling\n stream = fs.createWriteStream(options.logFile, { encoding: 'utf-8' });\n startFile(stream);\n }\n\n // Load tablet file and assemblies\n const assemblies = loadAssemblies(assemblyLocations, false);\n const defaultTablets = await loadAllDefaultTablets(assemblies);\n\n const availableTranslations = new LanguageTablet();\n if (options?.cacheFromFile) {\n availableTranslations.addTablet(await LanguageTablet.fromOptionalFile(options.cacheFromFile));\n }\n availableTranslations.addTablets(...Object.values(defaultTablets));\n\n const { translationsByFqn, originalsByKey } = await availableSnippetsPerFqn(assemblies, availableTranslations);\n\n const additionalOutputTablet = options?.cacheToFile\n ? await LanguageTablet.fromOptionalFile(options?.cacheToFile)\n : new LanguageTablet();\n\n const coverageResults = mkDict(\n await Promise.all(\n assemblies.map(async ({ assembly, directory }) => {\n stream?.write(`<h1>${assembly.name}</h1>\\n`);\n\n const implicitTablet = defaultTablets[directory];\n const implicitTabletFile = path.join(\n directory,\n implicitTablet.compressedSource ? DEFAULT_TABLET_NAME_COMPRESSED : DEFAULT_TABLET_NAME,\n );\n if (!implicitTablet) {\n throw new Error(`No tablet found for ${directory}`);\n }\n\n let insertedExamples = 0;\n const filteredTypes = filterForTypesWithoutExamples(assembly.types ?? {});\n for (const [typeFqn, type] of Object.entries(filteredTypes)) {\n const available = translationsByFqn[typeFqn];\n if (!available) {\n continue;\n }\n\n const example = pickBestExample(typeFqn, available, stream);\n const original = originalsByKey[example.key];\n insertExample(example, original, type, [implicitTablet, additionalOutputTablet]);\n insertedExamples++;\n }\n\n if (insertedExamples > 0) {\n // Save the updated assembly and implicit tablets\n // eslint-disable-next-line no-await-in-loop\n await Promise.all([\n replaceAssembly(assembly, directory),\n implicitTablet.save(implicitTabletFile, implicitTablet.compressedSource),\n ]);\n }\n\n return [\n directory,\n {\n types: Object.keys(filteredTypes).length,\n typesWithInsertedExamples: insertedExamples,\n } as InfuseTypes,\n ] as const;\n }),\n ),\n );\n\n stream?.close();\n\n // If we copied examples onto different types, we'll also have inserted new snippets\n // with different keys into the tablet. We must now write the updated tablet somewhere.\n if (options?.cacheToFile) {\n await additionalOutputTablet.save(options.cacheToFile, options.compressCacheToFile);\n }\n\n return {\n coverageResults: coverageResults,\n };\n}\n\nfunction pickBestExample(typeFqn: string, choices: TranslatedSnippet[], logStream?: fs.WriteStream) {\n const meanResult = mean(choices);\n if (logStream) {\n const selected = Object.entries(ADDITIONAL_SELECTORS).map(([name, fn]) => [name, fn(choices)] as const);\n const selectedFromSelector = {\n ...makeDict(selected),\n mean: meanResult,\n };\n logOutput(logStream, typeFqn, createHtmlEntry(selectedFromSelector));\n }\n return meanResult;\n}\n\nfunction startFile(stream: fs.WriteStream) {\n stream.write('<style>\\n');\n stream.write('h2 { color: blue; clear: both; }\\n');\n stream.write('h1 { color: red; clear: both; }\\n');\n stream.write(\n 'div { float: left; height: 31em; width: 22em; overflow: auto; margin: 1em; background-color: #ddd; }\\n',\n );\n stream.write(\n 'pre { float: left; height: 30em; width: 25em; overflow: auto; padding: 0.5em; background-color: #ddd; }\\n',\n );\n stream.write('</style>\\n');\n}\n\nfunction createHtmlEntry(results: Record<string, TranslatedSnippet>): Record<string, string[]> {\n const entry = new DefaultRecord<string>();\n for (const [key, value] of Object.entries(results)) {\n entry.add(value.originalSource.source, key);\n }\n return entry.index;\n}\n\nfunction logOutput(stream: fs.WriteStream | undefined, typeFqn: string, algorithmMap: Record<string, string[]>) {\n stream?.write(`<h2>${typeFqn}</h2>\\n`);\n for (const [key, value] of Object.entries(algorithmMap)) {\n stream?.write(`<div class=\"snippet\"><h3>${value.toString()}</h3>\\n<pre>${key}</pre>\\n</div>\\n`);\n }\n for (let i = 0; i < 4 - Object.keys(algorithmMap).length; i++) {\n stream?.write('<div class=\"padding\"></div>\\n');\n }\n}\n\nfunction filterForTypesWithoutExamples(types: { [fqn: string]: spec.Type }): Record<string, spec.Type> {\n const filteredTypes: Record<string, spec.Type> = {};\n for (const [typeFqn, type] of Object.entries(types)) {\n // Ignore Interfaces that contain only properties\n if (type.kind === spec.TypeKind.Interface && !type.datatype) {\n continue;\n }\n // Already has example\n if (type.docs?.example !== undefined) {\n continue;\n }\n filteredTypes[typeFqn] = type;\n }\n return filteredTypes;\n}\n\n/**\n * Insert an example into the docs of a type, and insert it back into the tablet under a new key\n */\nfunction insertExample(\n example: TranslatedSnippet,\n original: TypeScriptSnippet | undefined,\n type: spec.Type,\n tablets: LanguageTablet[],\n): void {\n const parameters = {\n ...original?.parameters,\n infused: '',\n };\n // exampleMetadata should always be nonempty since we always have a parameter.\n const exampleMetadata = renderMetadataline(parameters) ?? '';\n\n if (type.docs) {\n type.docs.example = example.originalSource.source;\n type.docs.custom = { ...type.docs.custom, exampleMetadata };\n } else {\n type.docs = {\n example: example.originalSource.source,\n custom: { exampleMetadata },\n };\n }\n\n for (const tablet of tablets) {\n tablet.addSnippets(\n example.withLocation({\n api: { api: 'type', fqn: type.fqn },\n field: { field: 'example' },\n }),\n );\n }\n}\n\n/**\n * Return a map of FQN -> snippet keys that exercise that FQN.\n *\n * For a snippet to qualify, it must both:\n *\n * a) be current (i.e.: exist in the input assemblies)\n * b) have been analyzed (i.e.: exist in one of the translated tablets)\n *\n * Returns a map of fqns to a list of keys that represent snippets that include the fqn.\n */\nasync function availableSnippetsPerFqn(asms: readonly LoadedAssembly[], translationsTablet: LanguageTablet) {\n const ret = new DefaultRecord<TranslatedSnippet>();\n\n const originalsByKey = indexBy(await allTypeScriptSnippets(asms), snippetKey);\n\n const translations = Object.keys(originalsByKey)\n .map((key) => translationsTablet.tryGetSnippet(key))\n .filter(isDefined);\n\n for (const trans of translations) {\n for (const fqn of trans.snippet.fqnsReferenced ?? []) {\n ret.add(fqn, trans);\n }\n }\n\n return { originalsByKey, translationsByFqn: ret.index };\n}\n\nfunction makeDict<A>(xs: Array<readonly [string, A]>): Record<string, A> {\n const ret: Record<string, A> = {};\n for (const [str, a] of xs) {\n ret[str] = a;\n }\n return ret;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"infuse.js","sourceRoot":"","sources":["../../src/commands/infuse.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as spec from '@jsii/spec';\nimport { replaceAssembly } from '@jsii/spec';\n\nimport { loadAssemblies, loadAllDefaultTablets, LoadedAssembly, allTypeScriptSnippets } from '../jsii/assemblies';\nimport { renderMetadataline, TypeScriptSnippet } from '../snippet';\nimport { SnippetSelector, mean, meanLength, shortest, longest } from '../snippet-selectors';\nimport { snippetKey } from '../tablets/key';\nimport {\n LanguageTablet,\n TranslatedSnippet,\n DEFAULT_TABLET_NAME,\n DEFAULT_TABLET_NAME_COMPRESSED,\n} from '../tablets/tablets';\nimport { isDefined, mkDict, indexBy } from '../util';\n\nexport interface InfuseResult {\n readonly coverageResults: Record<string, InfuseTypes>;\n}\n\nexport interface InfuseTypes {\n readonly types: number;\n readonly typesWithInsertedExamples: number;\n}\n\nexport interface InfuseOptions {\n readonly logFile?: string;\n\n /**\n * Where to read additional translations\n */\n readonly cacheFromFile?: string;\n\n /**\n * In addition to the implicit tablets, also write all added examples to this additional output tablet\n */\n readonly cacheToFile?: string;\n\n /**\n * Compress the cacheToFile\n */\n readonly compressCacheToFile?: boolean;\n}\n\nexport const DEFAULT_INFUSION_RESULTS_NAME = 'infusion-results.html';\n\nconst ADDITIONAL_SELECTORS: Record<string, SnippetSelector> = { meanLength, shortest, longest };\n\nclass DefaultRecord<A> {\n public readonly index: Record<string, A[]> = {};\n\n public add(key: string, value: A) {\n if (!this.index[key]) {\n this.index[key] = [];\n }\n this.index[key].push(value);\n }\n}\n\n/**\n * Infuse will analyze the snippets in a set of tablets, and update the assembly to add\n * examples to types that don't have any yet, based on snippets that use the given type.\n */\nexport async function infuse(assemblyLocations: string[], options?: InfuseOptions): Promise<InfuseResult> {\n let stream: fs.WriteStream | undefined = undefined;\n if (options?.logFile) {\n // Create stream for html file and insert some styling\n stream = fs.createWriteStream(options.logFile, { encoding: 'utf-8' });\n startFile(stream);\n }\n\n // Load tablet file and assemblies\n const assemblies = loadAssemblies(assemblyLocations, false);\n const defaultTablets = await loadAllDefaultTablets(assemblies);\n\n const availableTranslations = new LanguageTablet();\n if (options?.cacheFromFile) {\n availableTranslations.addTranslationsFromTablet(await LanguageTablet.fromOptionalFile(options.cacheFromFile));\n }\n availableTranslations.addTranslationsFromTablets(...Object.values(defaultTablets));\n\n const { translationsByFqn, originalsByKey } = await availableSnippetsPerFqn(assemblies, availableTranslations);\n\n const additionalOutputTablet = options?.cacheToFile\n ? await LanguageTablet.fromOptionalFile(options?.cacheToFile)\n : new LanguageTablet();\n\n const coverageResults = mkDict(\n await Promise.all(\n assemblies.map(async ({ assembly, directory }) => {\n stream?.write(`<h1>${assembly.name}</h1>\\n`);\n\n const implicitTablet = defaultTablets[directory];\n const implicitTabletFile = path.join(\n directory,\n implicitTablet.compressedSource ? DEFAULT_TABLET_NAME_COMPRESSED : DEFAULT_TABLET_NAME,\n );\n if (!implicitTablet) {\n throw new Error(`No tablet found for ${directory}`);\n }\n\n let insertedExamples = 0;\n const filteredTypes = filterForTypesWithoutExamples(assembly.types ?? {});\n for (const [typeFqn, type] of Object.entries(filteredTypes)) {\n const available = translationsByFqn[typeFqn];\n if (!available) {\n continue;\n }\n\n const example = pickBestExample(typeFqn, available, stream);\n const original = originalsByKey[example.key];\n insertExample(example, original, type, [implicitTablet, additionalOutputTablet]);\n insertedExamples++;\n }\n\n if (insertedExamples > 0) {\n // Save the updated assembly and implicit tablets\n // eslint-disable-next-line no-await-in-loop\n await Promise.all([\n replaceAssembly(assembly, directory),\n implicitTablet.save(implicitTabletFile, implicitTablet.compressedSource),\n ]);\n }\n\n return [\n directory,\n {\n types: Object.keys(filteredTypes).length,\n typesWithInsertedExamples: insertedExamples,\n } as InfuseTypes,\n ] as const;\n }),\n ),\n );\n\n stream?.close();\n\n // If we copied examples onto different types, we'll also have inserted new snippets\n // with different keys into the tablet. We must now write the updated tablet somewhere.\n if (options?.cacheToFile) {\n await additionalOutputTablet.save(options.cacheToFile, options.compressCacheToFile);\n }\n\n return {\n coverageResults: coverageResults,\n };\n}\n\nfunction pickBestExample(typeFqn: string, choices: TranslatedSnippet[], logStream?: fs.WriteStream) {\n const meanResult = mean(choices);\n if (logStream) {\n const selected = Object.entries(ADDITIONAL_SELECTORS).map(([name, fn]) => [name, fn(choices)] as const);\n const selectedFromSelector = {\n ...makeDict(selected),\n mean: meanResult,\n };\n logOutput(logStream, typeFqn, createHtmlEntry(selectedFromSelector));\n }\n return meanResult;\n}\n\nfunction startFile(stream: fs.WriteStream) {\n stream.write('<style>\\n');\n stream.write('h2 { color: blue; clear: both; }\\n');\n stream.write('h1 { color: red; clear: both; }\\n');\n stream.write(\n 'div { float: left; height: 31em; width: 22em; overflow: auto; margin: 1em; background-color: #ddd; }\\n',\n );\n stream.write(\n 'pre { float: left; height: 30em; width: 25em; overflow: auto; padding: 0.5em; background-color: #ddd; }\\n',\n );\n stream.write('</style>\\n');\n}\n\nfunction createHtmlEntry(results: Record<string, TranslatedSnippet>): Record<string, string[]> {\n const entry = new DefaultRecord<string>();\n for (const [key, value] of Object.entries(results)) {\n entry.add(value.originalSource.source, key);\n }\n return entry.index;\n}\n\nfunction logOutput(stream: fs.WriteStream | undefined, typeFqn: string, algorithmMap: Record<string, string[]>) {\n stream?.write(`<h2>${typeFqn}</h2>\\n`);\n for (const [key, value] of Object.entries(algorithmMap)) {\n stream?.write(`<div class=\"snippet\"><h3>${value.toString()}</h3>\\n<pre>${key}</pre>\\n</div>\\n`);\n }\n for (let i = 0; i < 4 - Object.keys(algorithmMap).length; i++) {\n stream?.write('<div class=\"padding\"></div>\\n');\n }\n}\n\nfunction filterForTypesWithoutExamples(types: { [fqn: string]: spec.Type }): Record<string, spec.Type> {\n const filteredTypes: Record<string, spec.Type> = {};\n for (const [typeFqn, type] of Object.entries(types)) {\n // Ignore Interfaces that contain only properties\n if (type.kind === spec.TypeKind.Interface && !type.datatype) {\n continue;\n }\n // Already has example\n if (type.docs?.example !== undefined) {\n continue;\n }\n filteredTypes[typeFqn] = type;\n }\n return filteredTypes;\n}\n\n/**\n * Insert an example into the docs of a type, and insert it back into the tablet under a new key\n */\nfunction insertExample(\n example: TranslatedSnippet,\n original: TypeScriptSnippet | undefined,\n type: spec.Type,\n tablets: LanguageTablet[],\n): void {\n const parameters = {\n ...original?.parameters,\n infused: '',\n };\n // exampleMetadata should always be nonempty since we always have a parameter.\n const exampleMetadata = renderMetadataline(parameters) ?? '';\n\n if (type.docs) {\n type.docs.example = example.originalSource.source;\n type.docs.custom = { ...type.docs.custom, exampleMetadata };\n } else {\n type.docs = {\n example: example.originalSource.source,\n custom: { exampleMetadata },\n };\n }\n\n for (const tablet of tablets) {\n tablet.addTranslations(\n example.withLocation({\n api: { api: 'type', fqn: type.fqn },\n field: { field: 'example' },\n }),\n );\n }\n}\n\n/**\n * Return a map of FQN -> snippet keys that exercise that FQN.\n *\n * For a snippet to qualify, it must both:\n *\n * a) be current (i.e.: exist in the input assemblies)\n * b) have been analyzed (i.e.: exist in one of the translated tablets)\n *\n * Returns a map of fqns to a list of keys that represent snippets that include the fqn.\n */\nasync function availableSnippetsPerFqn(asms: readonly LoadedAssembly[], translationsTablet: LanguageTablet) {\n const ret = new DefaultRecord<TranslatedSnippet>();\n\n const originalsByKey = indexBy(await allTypeScriptSnippets(asms), snippetKey);\n\n const translations = Object.keys(originalsByKey)\n .map((key) => translationsTablet.tryGetSnippet(key))\n .filter(isDefined);\n\n for (const trans of translations) {\n for (const fqn of trans.snippet.fqnsReferenced ?? []) {\n ret.add(fqn, trans);\n }\n }\n\n return { originalsByKey, translationsByFqn: ret.index };\n}\n\nfunction makeDict<A>(xs: Array<readonly [string, A]>): Record<string, A> {\n const ret: Record<string, A> = {};\n for (const [str, a] of xs) {\n ret[str] = a;\n }\n return ret;\n}\n"]}
|
|
@@ -12,7 +12,7 @@ async function trimCache(options) {
|
|
|
12
12
|
const snippets = Array.from(await (0, assemblies_1.allTypeScriptSnippets)(assemblies));
|
|
13
13
|
const original = await tablets_1.LanguageTablet.fromFile(options.cacheFile);
|
|
14
14
|
const updated = new tablets_1.LanguageTablet();
|
|
15
|
-
updated.
|
|
15
|
+
updated.addTranslations(...snippets.map((snip) => original.tryGetSnippet((0, key_1.snippetKey)(snip))).filter(util_1.isDefined));
|
|
16
16
|
// if the original file was compressed, then compress the updated file too
|
|
17
17
|
await updated.save(options.cacheFile, original.compressedSource);
|
|
18
18
|
// eslint-disable-next-line prettier/prettier
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trim-cache.js","sourceRoot":"","sources":["../../src/commands/trim-cache.ts"],"names":[],"mappings":";;AAkBA,8BAcC;AAhCD,mDAA2E;AAC3E,sCAAsC;AACtC,wCAA4C;AAC5C,gDAAoD;AACpD,kCAAoC;AAc7B,KAAK,UAAU,SAAS,CAAC,OAAyB;IACvD,OAAO,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,iBAAiB,CAAC,MAAM,aAAa,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,IAAA,2BAAc,EAAC,OAAO,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;IAEpE,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,IAAA,kCAAqB,EAAC,UAAU,CAAC,CAAC,CAAC;IAErE,MAAM,QAAQ,GAAG,MAAM,wBAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,IAAI,wBAAc,EAAE,CAAC;IACrC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"trim-cache.js","sourceRoot":"","sources":["../../src/commands/trim-cache.ts"],"names":[],"mappings":";;AAkBA,8BAcC;AAhCD,mDAA2E;AAC3E,sCAAsC;AACtC,wCAA4C;AAC5C,gDAAoD;AACpD,kCAAoC;AAc7B,KAAK,UAAU,SAAS,CAAC,OAAyB;IACvD,OAAO,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,iBAAiB,CAAC,MAAM,aAAa,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,IAAA,2BAAc,EAAC,OAAO,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;IAEpE,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,IAAA,kCAAqB,EAAC,UAAU,CAAC,CAAC,CAAC;IAErE,MAAM,QAAQ,GAAG,MAAM,wBAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,IAAI,wBAAc,EAAE,CAAC;IACrC,OAAO,CAAC,eAAe,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAA,gBAAU,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAS,CAAC,CAAC,CAAC;IAC/G,0EAA0E;IAC1E,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAEjE,6CAA6C;IAC7C,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,SAAS,KAAK,OAAO,CAAC,KAAK,wBAAwB,QAAQ,CAAC,KAAK,MAAM,OAAO,CAAC,KAAK,WAAW,CAAC,CAAC;AAC3H,CAAC","sourcesContent":["import { loadAssemblies, allTypeScriptSnippets } from '../jsii/assemblies';\nimport * as logging from '../logging';\nimport { snippetKey } from '../tablets/key';\nimport { LanguageTablet } from '../tablets/tablets';\nimport { isDefined } from '../util';\n\nexport interface TrimCacheOptions {\n /**\n * Locations of assemblies to search for snippets\n */\n readonly assemblyLocations: string[];\n\n /**\n * Cache to trim\n */\n readonly cacheFile: string;\n}\n\nexport async function trimCache(options: TrimCacheOptions): Promise<void> {\n logging.info(`Loading ${options.assemblyLocations.length} assemblies`);\n const assemblies = loadAssemblies(options.assemblyLocations, false);\n\n const snippets = Array.from(await allTypeScriptSnippets(assemblies));\n\n const original = await LanguageTablet.fromFile(options.cacheFile);\n const updated = new LanguageTablet();\n updated.addTranslations(...snippets.map((snip) => original.tryGetSnippet(snippetKey(snip))).filter(isDefined));\n // if the original file was compressed, then compress the updated file too\n await updated.save(options.cacheFile, original.compressedSource);\n\n // eslint-disable-next-line prettier/prettier\n logging.info(`${options.cacheFile}: ${updated.count} snippets remaining (${original.count} - ${updated.count} trimmed)`);\n}\n"]}
|
package/lib/rosetta-reader.js
CHANGED
|
@@ -166,12 +166,12 @@ class RosettaTabletReader {
|
|
|
166
166
|
const extracted = this.extractedSnippets.get((0, key_1.snippetKey)(source));
|
|
167
167
|
if (extracted !== undefined) {
|
|
168
168
|
const snippet = this.translator.translate(extracted, this.options.targetLanguages);
|
|
169
|
-
this.liveTablet.
|
|
169
|
+
this.liveTablet.addTranslations(snippet);
|
|
170
170
|
return this.prefixDisclaimer(snippet.get(targetLang), this._prefixDisclaimer);
|
|
171
171
|
}
|
|
172
172
|
// Try to live-convert it as-is.
|
|
173
173
|
const snippet = this.translator.translate(source, this.options.targetLanguages);
|
|
174
|
-
this.liveTablet.
|
|
174
|
+
this.liveTablet.addTranslations(snippet);
|
|
175
175
|
return this.prefixDisclaimer(snippet.get(targetLang), this._prefixDisclaimer);
|
|
176
176
|
}
|
|
177
177
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rosetta-reader.js","sourceRoot":"","sources":["../src/rosetta-reader.ts"],"names":[],"mappings":"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","sourcesContent":["import * as spec from '@jsii/spec';\n\nimport { allTypeScriptSnippets, guessTabletLocation, SUPPORTED_ASSEMBLY_FEATURES } from './jsii/assemblies';\nimport { TargetLanguage } from './languages';\nimport * as logging from './logging';\nimport { transformMarkdown } from './markdown/markdown';\nimport { MarkdownRenderer } from './markdown/markdown-renderer';\nimport { ReplaceTypeScriptTransform } from './markdown/replace-typescript-transform';\nimport { CodeBlock } from './markdown/types';\nimport {\n SnippetParameters,\n TypeScriptSnippet,\n updateParameters,\n ApiLocation,\n typeScriptSnippetFromSource,\n} from './snippet';\nimport { snippetKey } from './tablets/key';\nimport { LanguageTablet, Translation } from './tablets/tablets';\nimport { Translator } from './translate';\nimport { commentToken, pathExists, printDiagnostics } from './util';\n\nexport enum UnknownSnippetMode {\n /**\n * Return the snippet as given (untranslated)\n */\n VERBATIM = 'verbatim',\n\n /**\n * Live-translate the snippet as best as we can\n */\n TRANSLATE = 'translate',\n\n /**\n * Throw an error if this occurs\n */\n FAIL = 'fail',\n}\n\nexport interface RosettaOptions {\n /**\n * Whether or not to live-convert samples\n *\n * @default UnknownSnippetMode.VERBATIM\n */\n readonly unknownSnippets?: UnknownSnippetMode;\n\n /**\n * Target languages to use for live conversion\n *\n * @default All languages\n */\n readonly targetLanguages?: readonly TargetLanguage[];\n\n /**\n * Whether to include compiler diagnostics in the compilation results.\n */\n readonly includeCompilerDiagnostics?: boolean;\n\n /**\n * Whether this Rosetta should operate in \"loose\" mode, where missing literate\n * source files and missing fixtures are ignored instead of failing.\n *\n * @default false\n */\n readonly loose?: boolean;\n\n /**\n * Adds a disclaimer to start of snippet if it did not compile.\n *\n * @default false\n */\n readonly prefixDisclaimer?: boolean;\n}\n\n/**\n * Entry point class for consumers of Rosetta tablets (primarily: pacmak)\n *\n * Rosetta can work in one of two modes:\n *\n * 1. Live translation of snippets.\n * 2. Read translations from a pre-translated tablet (prepared using `jsii-rosetta extract` command).\n *\n * The second method affords more control over the precise circumstances of\n * sample compilation and is recommended, but the first method will do\n * when the second one is not necessary.\n */\nexport class RosettaTabletReader {\n /**\n * The assembly features that the current version of `jsii-rosetta` supports.\n */\n public static get supportedAssemblyFeatures(): spec.JsiiFeature[] {\n return SUPPORTED_ASSEMBLY_FEATURES;\n }\n\n /**\n * Newly translated samples\n *\n * In case live translation has been enabled, all samples that have been translated on-the-fly\n * are added to this tablet.\n */\n public readonly liveTablet = new LanguageTablet();\n\n private readonly loadedTablets: LanguageTablet[] = [];\n private readonly extractedSnippets = new Map<string, TypeScriptSnippet>();\n private readonly translator: Translator;\n private readonly loose: boolean;\n private readonly unknownSnippets: UnknownSnippetMode;\n private readonly _prefixDisclaimer: boolean;\n\n public constructor(private readonly options: RosettaOptions = {}) {\n this.loose = !!options.loose;\n this.unknownSnippets = options.unknownSnippets ?? UnknownSnippetMode.VERBATIM;\n this.translator = new Translator(options.includeCompilerDiagnostics ?? false);\n this._prefixDisclaimer = options.prefixDisclaimer ?? false;\n }\n\n /**\n * Diagnostics encountered while doing live translation\n */\n public get diagnostics() {\n return this.translator.diagnostics;\n }\n\n /**\n * Load a tablet as a source for translateable snippets\n *\n * Note: the snippets loaded from this tablet will NOT be validated for\n * their fingerprints or translator versions! If a matching snippet is found\n * in the tablet, it will always be returned, whether or not it is stale.\n */\n public async loadTabletFromFile(tabletFile: string) {\n const tablet = new LanguageTablet();\n await tablet.load(tabletFile);\n this.addTablet(tablet);\n }\n\n /**\n * Directly add a tablet to the list of tablets to load translations from\n */\n public addTablet(tablet: LanguageTablet) {\n this.loadedTablets.push(tablet);\n }\n\n /**\n * Add an assembly\n *\n * If a default tablet file is found in the assembly's directory, it will be\n * loaded (and assumed to contain a complete list of translated snippets for\n * this assembly already).\n *\n * Otherwise, if live conversion is enabled, the snippets in the assembly\n * become available for live translation later. This is necessary because we probably\n * need to fixturize snippets for successful compilation, and the information\n * pacmak sends our way later on is not going to be enough to do that.\n */\n public async addAssembly(assembly: spec.Assembly, assemblyDir: string) {\n const defaultTablet = guessTabletLocation(assemblyDir);\n if (await pathExists(defaultTablet)) {\n try {\n await this.loadTabletFromFile(defaultTablet);\n return;\n } catch (e: any) {\n logging.warn(`Error loading ${defaultTablet}: ${e.message}. Skipped.`);\n }\n }\n\n // Inventarize the snippets from this assembly, but only if there's a chance\n // we're going to need them.\n if (this.unknownSnippets === UnknownSnippetMode.TRANSLATE) {\n for (const tsnip of await allTypeScriptSnippets([{ assembly, directory: assemblyDir }], this.loose)) {\n this.extractedSnippets.set(snippetKey(tsnip), tsnip);\n }\n }\n }\n\n /**\n * Translate the given snippet for the given target language\n *\n * This will either:\n *\n * - Find an existing translation in a tablet and return that, if available.\n * - Otherwise, find a fixturized version of this snippet in an assembly that\n * was loaded beforehand, and translate it on-the-fly. Finding the fixture\n * will be based on the snippet key, which consists of a hash of the\n * visible source and the API location.\n * - Otherwise, translate the snippet as-is (without fixture information).\n *\n * This will do and store a full conversion of the given snippet, even if it only\n * returns one language. Subsequent retrievals for the same snippet in other\n * languages will reuse the translation from cache.\n *\n * If you are calling this for the side effect of adding translations to the live\n * tablet, you only need to do that for one language.\n */\n public translateSnippet(source: TypeScriptSnippet, targetLang: TargetLanguage): Translation | undefined {\n // Look for it in loaded tablets (or previous conversions)\n for (const tab of this.allTablets) {\n const ret = tab.lookup(source, targetLang);\n if (ret !== undefined) {\n return this.prefixDisclaimer(ret, this._prefixDisclaimer);\n }\n }\n\n if (this.unknownSnippets === UnknownSnippetMode.VERBATIM) {\n return this.prefixDisclaimer(\n {\n language: targetLang,\n source: source.visibleSource,\n },\n this._prefixDisclaimer,\n );\n }\n\n if (this.unknownSnippets === UnknownSnippetMode.FAIL) {\n const message = [\n 'The following snippet was not found in any of the loaded tablets:',\n source.visibleSource,\n `Location: ${JSON.stringify(source.location)}`,\n `Language: ${targetLang}`,\n ].join('\\n');\n throw new Error(message);\n }\n\n if (this.options.targetLanguages && !this.options.targetLanguages.includes(targetLang)) {\n throw new Error(\n `Rosetta configured for live conversion to ${this.options.targetLanguages.join(\n ', ',\n )}, but requested ${targetLang}`,\n );\n }\n\n // See if we can find a fixturized version of this snippet. If so, use that do the live\n // conversion.\n const extracted = this.extractedSnippets.get(snippetKey(source));\n if (extracted !== undefined) {\n const snippet = this.translator.translate(extracted, this.options.targetLanguages);\n this.liveTablet.addSnippets(snippet);\n return this.prefixDisclaimer(snippet.get(targetLang), this._prefixDisclaimer);\n }\n\n // Try to live-convert it as-is.\n const snippet = this.translator.translate(source, this.options.targetLanguages);\n this.liveTablet.addSnippets(snippet);\n return this.prefixDisclaimer(snippet.get(targetLang), this._prefixDisclaimer);\n }\n\n /**\n * Translate a snippet found in the \"@ example\" section of a jsii assembly\n *\n * Behaves exactly like `translateSnippet`, so see that method for documentation.\n */\n public translateExample(\n apiLocation: ApiLocation,\n example: string,\n targetLang: TargetLanguage,\n strict: boolean,\n compileDirectory = process.cwd(),\n ): Translation {\n const location = { api: apiLocation, field: { field: 'example' } } as const;\n\n const snippet = typeScriptSnippetFromSource(example, location, strict, {\n [SnippetParameters.$COMPILATION_DIRECTORY]: compileDirectory,\n });\n\n const translated = this.translateSnippet(snippet, targetLang);\n\n return translated ?? { language: 'typescript', source: example };\n }\n\n /**\n * Translate all TypeScript snippets found in a block of Markdown text\n *\n * For each snippet, behaves exactly like `translateSnippet`, so see that\n * method for documentation.\n */\n public translateSnippetsInMarkdown(\n apiLocation: ApiLocation,\n markdown: string,\n targetLang: TargetLanguage,\n strict: boolean,\n translationToCodeBlock: (x: Translation) => CodeBlock = id,\n compileDirectory = process.cwd(),\n ): string {\n return transformMarkdown(\n markdown,\n new MarkdownRenderer(),\n new ReplaceTypeScriptTransform(apiLocation, strict, (tsSnip) => {\n const translated = this.translateSnippet(\n updateParameters(tsSnip, {\n [SnippetParameters.$COMPILATION_DIRECTORY]: compileDirectory,\n }),\n targetLang,\n );\n if (!translated) {\n return undefined;\n }\n\n return translationToCodeBlock(translated);\n }),\n );\n }\n\n public printDiagnostics(stream: NodeJS.WritableStream, colors = true) {\n printDiagnostics(this.diagnostics, stream, colors);\n }\n\n public get hasErrors() {\n return this.diagnostics.some((d) => d.isError);\n }\n\n private get allTablets(): LanguageTablet[] {\n return [...this.loadedTablets, this.liveTablet];\n }\n\n /**\n * Adds a disclaimer to the front of the example if the prefixDisclaimer\n * flag is set and we know it does not compile.\n */\n private prefixDisclaimer(translation: Translation | undefined, prefixDisclaimer: boolean): Translation | undefined {\n if (!prefixDisclaimer || translation?.didCompile !== false) {\n return translation;\n }\n const comment = commentToken(translation.language);\n const disclaimer = 'Example automatically generated from non-compiling source. May contain errors.';\n return {\n ...translation,\n source: `${comment} ${disclaimer}\\n${translation.source}`,\n };\n }\n}\n\nfunction id(x: Translation) {\n return x;\n}\n\n/**\n * Backwards compatibility\n *\n * @deprecated use RosettaTabletReader instead\n */\nexport class Rosetta extends RosettaTabletReader {}\n"]}
|
|
1
|
+
{"version":3,"file":"rosetta-reader.js","sourceRoot":"","sources":["../src/rosetta-reader.ts"],"names":[],"mappings":"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","sourcesContent":["import * as spec from '@jsii/spec';\n\nimport { allTypeScriptSnippets, guessTabletLocation, SUPPORTED_ASSEMBLY_FEATURES } from './jsii/assemblies';\nimport { TargetLanguage } from './languages';\nimport * as logging from './logging';\nimport { transformMarkdown } from './markdown/markdown';\nimport { MarkdownRenderer } from './markdown/markdown-renderer';\nimport { ReplaceTypeScriptTransform } from './markdown/replace-typescript-transform';\nimport { CodeBlock } from './markdown/types';\nimport {\n SnippetParameters,\n TypeScriptSnippet,\n updateParameters,\n ApiLocation,\n typeScriptSnippetFromSource,\n} from './snippet';\nimport { snippetKey } from './tablets/key';\nimport { LanguageTablet, Translation } from './tablets/tablets';\nimport { Translator } from './translate';\nimport { commentToken, pathExists, printDiagnostics } from './util';\n\nexport enum UnknownSnippetMode {\n /**\n * Return the snippet as given (untranslated)\n */\n VERBATIM = 'verbatim',\n\n /**\n * Live-translate the snippet as best as we can\n */\n TRANSLATE = 'translate',\n\n /**\n * Throw an error if this occurs\n */\n FAIL = 'fail',\n}\n\nexport interface RosettaOptions {\n /**\n * Whether or not to live-convert samples\n *\n * @default UnknownSnippetMode.VERBATIM\n */\n readonly unknownSnippets?: UnknownSnippetMode;\n\n /**\n * Target languages to use for live conversion\n *\n * @default All languages\n */\n readonly targetLanguages?: readonly TargetLanguage[];\n\n /**\n * Whether to include compiler diagnostics in the compilation results.\n */\n readonly includeCompilerDiagnostics?: boolean;\n\n /**\n * Whether this Rosetta should operate in \"loose\" mode, where missing literate\n * source files and missing fixtures are ignored instead of failing.\n *\n * @default false\n */\n readonly loose?: boolean;\n\n /**\n * Adds a disclaimer to start of snippet if it did not compile.\n *\n * @default false\n */\n readonly prefixDisclaimer?: boolean;\n}\n\n/**\n * Entry point class for consumers of Rosetta tablets (primarily: pacmak)\n *\n * Rosetta can work in one of two modes:\n *\n * 1. Live translation of snippets.\n * 2. Read translations from a pre-translated tablet (prepared using `jsii-rosetta extract` command).\n *\n * The second method affords more control over the precise circumstances of\n * sample compilation and is recommended, but the first method will do\n * when the second one is not necessary.\n */\nexport class RosettaTabletReader {\n /**\n * The assembly features that the current version of `jsii-rosetta` supports.\n */\n public static get supportedAssemblyFeatures(): spec.JsiiFeature[] {\n return SUPPORTED_ASSEMBLY_FEATURES;\n }\n\n /**\n * Newly translated samples\n *\n * In case live translation has been enabled, all samples that have been translated on-the-fly\n * are added to this tablet.\n */\n public readonly liveTablet = new LanguageTablet();\n\n private readonly loadedTablets: LanguageTablet[] = [];\n private readonly extractedSnippets = new Map<string, TypeScriptSnippet>();\n private readonly translator: Translator;\n private readonly loose: boolean;\n private readonly unknownSnippets: UnknownSnippetMode;\n private readonly _prefixDisclaimer: boolean;\n\n public constructor(private readonly options: RosettaOptions = {}) {\n this.loose = !!options.loose;\n this.unknownSnippets = options.unknownSnippets ?? UnknownSnippetMode.VERBATIM;\n this.translator = new Translator(options.includeCompilerDiagnostics ?? false);\n this._prefixDisclaimer = options.prefixDisclaimer ?? false;\n }\n\n /**\n * Diagnostics encountered while doing live translation\n */\n public get diagnostics() {\n return this.translator.diagnostics;\n }\n\n /**\n * Load a tablet as a source for translateable snippets\n *\n * Note: the snippets loaded from this tablet will NOT be validated for\n * their fingerprints or translator versions! If a matching snippet is found\n * in the tablet, it will always be returned, whether or not it is stale.\n */\n public async loadTabletFromFile(tabletFile: string) {\n const tablet = new LanguageTablet();\n await tablet.load(tabletFile);\n this.addTablet(tablet);\n }\n\n /**\n * Directly add a tablet to the list of tablets to load translations from\n */\n public addTablet(tablet: LanguageTablet) {\n this.loadedTablets.push(tablet);\n }\n\n /**\n * Add an assembly\n *\n * If a default tablet file is found in the assembly's directory, it will be\n * loaded (and assumed to contain a complete list of translated snippets for\n * this assembly already).\n *\n * Otherwise, if live conversion is enabled, the snippets in the assembly\n * become available for live translation later. This is necessary because we probably\n * need to fixturize snippets for successful compilation, and the information\n * pacmak sends our way later on is not going to be enough to do that.\n */\n public async addAssembly(assembly: spec.Assembly, assemblyDir: string) {\n const defaultTablet = guessTabletLocation(assemblyDir);\n if (await pathExists(defaultTablet)) {\n try {\n await this.loadTabletFromFile(defaultTablet);\n return;\n } catch (e: any) {\n logging.warn(`Error loading ${defaultTablet}: ${e.message}. Skipped.`);\n }\n }\n\n // Inventarize the snippets from this assembly, but only if there's a chance\n // we're going to need them.\n if (this.unknownSnippets === UnknownSnippetMode.TRANSLATE) {\n for (const tsnip of await allTypeScriptSnippets([{ assembly, directory: assemblyDir }], this.loose)) {\n this.extractedSnippets.set(snippetKey(tsnip), tsnip);\n }\n }\n }\n\n /**\n * Translate the given snippet for the given target language\n *\n * This will either:\n *\n * - Find an existing translation in a tablet and return that, if available.\n * - Otherwise, find a fixturized version of this snippet in an assembly that\n * was loaded beforehand, and translate it on-the-fly. Finding the fixture\n * will be based on the snippet key, which consists of a hash of the\n * visible source and the API location.\n * - Otherwise, translate the snippet as-is (without fixture information).\n *\n * This will do and store a full conversion of the given snippet, even if it only\n * returns one language. Subsequent retrievals for the same snippet in other\n * languages will reuse the translation from cache.\n *\n * If you are calling this for the side effect of adding translations to the live\n * tablet, you only need to do that for one language.\n */\n public translateSnippet(source: TypeScriptSnippet, targetLang: TargetLanguage): Translation | undefined {\n // Look for it in loaded tablets (or previous conversions)\n for (const tab of this.allTablets) {\n const ret = tab.lookup(source, targetLang);\n if (ret !== undefined) {\n return this.prefixDisclaimer(ret, this._prefixDisclaimer);\n }\n }\n\n if (this.unknownSnippets === UnknownSnippetMode.VERBATIM) {\n return this.prefixDisclaimer(\n {\n language: targetLang,\n source: source.visibleSource,\n },\n this._prefixDisclaimer,\n );\n }\n\n if (this.unknownSnippets === UnknownSnippetMode.FAIL) {\n const message = [\n 'The following snippet was not found in any of the loaded tablets:',\n source.visibleSource,\n `Location: ${JSON.stringify(source.location)}`,\n `Language: ${targetLang}`,\n ].join('\\n');\n throw new Error(message);\n }\n\n if (this.options.targetLanguages && !this.options.targetLanguages.includes(targetLang)) {\n throw new Error(\n `Rosetta configured for live conversion to ${this.options.targetLanguages.join(\n ', ',\n )}, but requested ${targetLang}`,\n );\n }\n\n // See if we can find a fixturized version of this snippet. If so, use that do the live\n // conversion.\n const extracted = this.extractedSnippets.get(snippetKey(source));\n if (extracted !== undefined) {\n const snippet = this.translator.translate(extracted, this.options.targetLanguages);\n this.liveTablet.addTranslations(snippet);\n return this.prefixDisclaimer(snippet.get(targetLang), this._prefixDisclaimer);\n }\n\n // Try to live-convert it as-is.\n const snippet = this.translator.translate(source, this.options.targetLanguages);\n this.liveTablet.addTranslations(snippet);\n return this.prefixDisclaimer(snippet.get(targetLang), this._prefixDisclaimer);\n }\n\n /**\n * Translate a snippet found in the \"@ example\" section of a jsii assembly\n *\n * Behaves exactly like `translateSnippet`, so see that method for documentation.\n */\n public translateExample(\n apiLocation: ApiLocation,\n example: string,\n targetLang: TargetLanguage,\n strict: boolean,\n compileDirectory = process.cwd(),\n ): Translation {\n const location = { api: apiLocation, field: { field: 'example' } } as const;\n\n const snippet = typeScriptSnippetFromSource(example, location, strict, {\n [SnippetParameters.$COMPILATION_DIRECTORY]: compileDirectory,\n });\n\n const translated = this.translateSnippet(snippet, targetLang);\n\n return translated ?? { language: 'typescript', source: example };\n }\n\n /**\n * Translate all TypeScript snippets found in a block of Markdown text\n *\n * For each snippet, behaves exactly like `translateSnippet`, so see that\n * method for documentation.\n */\n public translateSnippetsInMarkdown(\n apiLocation: ApiLocation,\n markdown: string,\n targetLang: TargetLanguage,\n strict: boolean,\n translationToCodeBlock: (x: Translation) => CodeBlock = id,\n compileDirectory = process.cwd(),\n ): string {\n return transformMarkdown(\n markdown,\n new MarkdownRenderer(),\n new ReplaceTypeScriptTransform(apiLocation, strict, (tsSnip) => {\n const translated = this.translateSnippet(\n updateParameters(tsSnip, {\n [SnippetParameters.$COMPILATION_DIRECTORY]: compileDirectory,\n }),\n targetLang,\n );\n if (!translated) {\n return undefined;\n }\n\n return translationToCodeBlock(translated);\n }),\n );\n }\n\n public printDiagnostics(stream: NodeJS.WritableStream, colors = true) {\n printDiagnostics(this.diagnostics, stream, colors);\n }\n\n public get hasErrors() {\n return this.diagnostics.some((d) => d.isError);\n }\n\n private get allTablets(): LanguageTablet[] {\n return [...this.loadedTablets, this.liveTablet];\n }\n\n /**\n * Adds a disclaimer to the front of the example if the prefixDisclaimer\n * flag is set and we know it does not compile.\n */\n private prefixDisclaimer(translation: Translation | undefined, prefixDisclaimer: boolean): Translation | undefined {\n if (!prefixDisclaimer || translation?.didCompile !== false) {\n return translation;\n }\n const comment = commentToken(translation.language);\n const disclaimer = 'Example automatically generated from non-compiling source. May contain errors.';\n return {\n ...translation,\n source: `${comment} ${disclaimer}\\n${translation.source}`,\n };\n }\n}\n\nfunction id(x: Translation) {\n return x;\n}\n\n/**\n * Backwards compatibility\n *\n * @deprecated use RosettaTabletReader instead\n */\nexport class Rosetta extends RosettaTabletReader {}\n"]}
|
|
@@ -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.
|
|
45
|
+
this.cache.addTranslationsFromTablet(tab);
|
|
46
46
|
}
|
|
47
47
|
addTabletsToCache(...tablets) {
|
|
48
48
|
for (const tab of tablets) {
|
|
49
|
-
this.cache.
|
|
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.
|
|
74
|
+
this.tablet.addTranslations(fromCache.snippet);
|
|
75
75
|
}
|
|
76
76
|
translations.push(fromCache.snippet);
|
|
77
77
|
infusedCount += fromCache.infused ? 1 : 0;
|
|
@@ -145,7 +145,7 @@ class RosettaTranslator {
|
|
|
145
145
|
this.fingerprinter.writeDebugFile(process.env.DEBUG_TYPE_FINGERPRINTS);
|
|
146
146
|
}
|
|
147
147
|
if (options?.addToTablet ?? true) {
|
|
148
|
-
this.tablet.
|
|
148
|
+
this.tablet.addTranslations(...fingerprinted);
|
|
149
149
|
}
|
|
150
150
|
return {
|
|
151
151
|
translatedSnippets: fingerprinted,
|
|
@@ -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 (process.env.DEBUG_TYPE_FINGERPRINTS) {\n this.fingerprinter.writeDebugFile(process.env.DEBUG_TYPE_FINGERPRINTS);\n }\n\n if (options?.addToTablet ?? true) {\n this.tablet.addSnippets(...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"]}
|
|
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"]}
|
package/lib/tablets/tablets.d.ts
CHANGED
|
@@ -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
|
-
|
|
39
|
+
addTranslations(...snippets: TranslatedSnippet[]): void;
|
|
38
40
|
/**
|
|
39
|
-
* Add one
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
package/lib/tablets/tablets.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
76
|
-
|
|
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
|
-
|
|
88
|
+
addTranslationsFromTablets(...tablets) {
|
|
85
89
|
for (const tablet of tablets) {
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
97
|
-
this.
|
|
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"]}
|