jsii-rosetta 1.74.0 → 1.76.0

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.
Files changed (49) hide show
  1. package/jest.config.mjs +1 -0
  2. package/lib/languages/csharp.js +13 -13
  3. package/lib/languages/default.d.ts +2 -1
  4. package/lib/languages/default.js +3 -2
  5. package/lib/languages/go.d.ts +3 -2
  6. package/lib/languages/go.js +61 -18
  7. package/lib/languages/java.d.ts +2 -1
  8. package/lib/languages/java.js +18 -4
  9. package/lib/languages/python.d.ts +3 -2
  10. package/lib/languages/python.js +8 -4
  11. package/lib/languages/record-references.d.ts +3 -2
  12. package/lib/languages/record-references.js +3 -3
  13. package/lib/languages/target-language.d.ts +26 -1
  14. package/lib/languages/target-language.js +39 -1
  15. package/lib/languages/visualize.d.ts +2 -0
  16. package/lib/languages/visualize.js +2 -0
  17. package/lib/renderer.d.ts +5 -2
  18. package/lib/renderer.js +109 -145
  19. package/lib/submodule-reference.d.ts +13 -0
  20. package/lib/submodule-reference.js +144 -0
  21. package/lib/translate.d.ts +1 -0
  22. package/lib/translate.js +14 -4
  23. package/lib/typescript/imports.d.ts +12 -1
  24. package/lib/typescript/imports.js +96 -26
  25. package/package.json +6 -5
  26. package/test/commands/transliterate.test.js +1 -1
  27. package/test/jsii-imports.test.js +3 -3
  28. package/test/translations/calls/shorthand_property.cs +2 -2
  29. package/test/translations/calls/will_type_deep_structs_directly_if_type_info_is_available.go +4 -4
  30. package/test/translations/expressions/await.cs +1 -1
  31. package/test/translations/expressions/backtick_string_w_o_substitutions.cs +1 -1
  32. package/test/translations/expressions/computed_key.cs +1 -1
  33. package/test/translations/expressions/string_interpolation.cs +2 -2
  34. package/test/translations/expressions/string_literal.cs +2 -2
  35. package/test/translations/expressions/string_literal.go +9 -1
  36. package/test/translations/expressions/string_literal.java +1 -1
  37. package/test/translations/expressions/string_literal.py +1 -1
  38. package/test/translations/expressions/struct_assignment.cs +1 -1
  39. package/test/translations/imports/selective_import.java +3 -3
  40. package/test/translations/imports/submodule-import.cs +15 -0
  41. package/test/translations/imports/submodule-import.go +23 -0
  42. package/test/translations/imports/submodule-import.java +17 -0
  43. package/test/translations/imports/submodule-import.py +15 -0
  44. package/test/translations/statements/statements_and_newlines.cs +4 -4
  45. package/test/translations/structs/infer_struct_from_union.go +3 -3
  46. package/test/translations/structs/optional_known_struct.go +1 -1
  47. package/test/translations/structs/struct_starting_with_i.go +1 -1
  48. package/test/translations/structs/var_new_class_known_struct.cs +1 -1
  49. package/test/translations/structs/var_new_class_known_struct.go +1 -1
package/lib/renderer.js CHANGED
@@ -15,11 +15,12 @@ const types_1 = require("./typescript/types");
15
15
  * the type of which should be expressed via the C parameter.
16
16
  */
17
17
  class AstRenderer {
18
- constructor(sourceFile, typeChecker, handler, options = {}) {
18
+ constructor(sourceFile, typeChecker, handler, options = {}, submoduleReferences = new Map()) {
19
19
  this.sourceFile = sourceFile;
20
20
  this.typeChecker = typeChecker;
21
21
  this.handler = handler;
22
22
  this.options = options;
23
+ this.submoduleReferences = submoduleReferences;
23
24
  this.diagnostics = new Array();
24
25
  this.currentContext = handler.defaultContext;
25
26
  }
@@ -190,152 +191,115 @@ class AstRenderer {
190
191
  * Dispatch node to handler
191
192
  */
192
193
  dispatch(tree) {
193
- // Special nodes
194
- if (ts.isEmptyStatement(tree)) {
195
- // Additional semicolon where it doesn't belong.
196
- return o_tree_1.NO_SYNTAX;
197
- }
198
194
  const visitor = this.handler;
199
- // Nodes with meaning
200
- if (ts.isSourceFile(tree)) {
201
- return visitor.sourceFile(tree, this);
202
- }
203
- if (ts.isImportEqualsDeclaration(tree)) {
204
- return visitor.importStatement((0, imports_1.analyzeImportEquals)(tree, this), this);
205
- }
206
- if (ts.isImportDeclaration(tree)) {
207
- return visitor.importStatement((0, imports_1.analyzeImportDeclaration)(tree, this), this);
208
- }
209
- if (ts.isStringLiteral(tree) || ts.isNoSubstitutionTemplateLiteral(tree)) {
210
- return visitor.stringLiteral(tree, this);
211
- }
212
- if (ts.isNumericLiteral(tree)) {
213
- return visitor.numericLiteral(tree, this);
214
- }
215
- if (ts.isFunctionDeclaration(tree)) {
216
- return visitor.functionDeclaration(tree, this);
217
- }
218
- if (ts.isIdentifier(tree)) {
219
- return visitor.identifier(tree, this);
220
- }
221
- if (ts.isBlock(tree)) {
222
- return visitor.block(tree, this);
223
- }
224
- if (ts.isParameter(tree)) {
225
- return visitor.parameterDeclaration(tree, this);
226
- }
227
- if (ts.isReturnStatement(tree)) {
228
- return visitor.returnStatement(tree, this);
229
- }
230
- if (ts.isBinaryExpression(tree)) {
231
- return visitor.binaryExpression(tree, this);
232
- }
233
- if (ts.isIfStatement(tree)) {
234
- return visitor.ifStatement(tree, this);
235
- }
236
- if (ts.isPropertyAccessExpression(tree)) {
237
- return visitor.propertyAccessExpression(tree, this);
238
- }
239
- if (ts.isAwaitExpression(tree)) {
240
- return visitor.awaitExpression(tree, this);
241
- }
242
- if (ts.isCallExpression(tree)) {
243
- return visitor.callExpression(tree, this);
244
- }
245
- if (ts.isExpressionStatement(tree)) {
246
- return visitor.expressionStatement(tree, this);
247
- }
248
- if (ts.isToken(tree)) {
249
- return visitor.token(tree, this);
250
- }
251
- if (ts.isObjectLiteralExpression(tree)) {
252
- return visitor.objectLiteralExpression(tree, this);
253
- }
254
- if (ts.isNewExpression(tree)) {
255
- return visitor.newExpression(tree, this);
256
- }
257
- if (ts.isPropertyAssignment(tree)) {
258
- return visitor.propertyAssignment(tree, this);
259
- }
260
- if (ts.isVariableStatement(tree)) {
261
- return visitor.variableStatement(tree, this);
262
- }
263
- if (ts.isVariableDeclarationList(tree)) {
264
- return visitor.variableDeclarationList(tree, this);
265
- }
266
- if (ts.isVariableDeclaration(tree)) {
267
- return visitor.variableDeclaration(tree, this);
268
- }
269
- if (ts.isJSDoc(tree)) {
270
- return visitor.jsDoc(tree, this);
271
- }
272
- if (ts.isArrayLiteralExpression(tree)) {
273
- return visitor.arrayLiteralExpression(tree, this);
274
- }
275
- if (ts.isShorthandPropertyAssignment(tree)) {
276
- return visitor.shorthandPropertyAssignment(tree, this);
277
- }
278
- if (ts.isForOfStatement(tree)) {
279
- return visitor.forOfStatement(tree, this);
280
- }
281
- if (ts.isClassDeclaration(tree)) {
282
- return visitor.classDeclaration(tree, this);
283
- }
284
- if (ts.isConstructorDeclaration(tree)) {
285
- return visitor.constructorDeclaration(tree, this);
286
- }
287
- if (ts.isPropertyDeclaration(tree)) {
288
- return visitor.propertyDeclaration(tree, this);
289
- }
290
- if (ts.isComputedPropertyName(tree)) {
291
- return visitor.computedPropertyName(tree.expression, this);
292
- }
293
- if (ts.isMethodDeclaration(tree)) {
294
- return visitor.methodDeclaration(tree, this);
295
- }
296
- if (ts.isInterfaceDeclaration(tree)) {
297
- return visitor.interfaceDeclaration(tree, this);
298
- }
299
- if (ts.isPropertySignature(tree)) {
300
- return visitor.propertySignature(tree, this);
301
- }
302
- if (ts.isMethodSignature(tree)) {
303
- return visitor.methodSignature(tree, this);
304
- }
305
- if (ts.isAsExpression(tree)) {
306
- return visitor.asExpression(tree, this);
307
- }
308
- if (ts.isPrefixUnaryExpression(tree)) {
309
- return visitor.prefixUnaryExpression(tree, this);
310
- }
311
- if (ts.isSpreadAssignment(tree)) {
312
- if (this.textOf(tree) === '...') {
313
- return visitor.ellipsis(tree, this);
314
- }
315
- return visitor.spreadAssignment(tree, this);
316
- }
317
- if (ts.isSpreadElement(tree)) {
318
- if (this.textOf(tree) === '...') {
319
- return visitor.ellipsis(tree, this);
320
- }
321
- return visitor.spreadElement(tree, this);
322
- }
323
- if (ts.isElementAccessExpression(tree)) {
324
- return visitor.elementAccessExpression(tree, this);
325
- }
326
- if (ts.isTemplateExpression(tree)) {
327
- return visitor.templateExpression(tree, this);
328
- }
329
- if (ts.isNonNullExpression(tree)) {
330
- return visitor.nonNullExpression(tree, this);
331
- }
332
- if (ts.isParenthesizedExpression(tree)) {
333
- return visitor.parenthesizedExpression(tree, this);
334
- }
335
- if (ts.isVoidExpression(tree)) {
336
- return visitor.maskingVoidExpression(tree, this);
195
+ // Using a switch on tree.kind + forced down-casting, because this is significantly faster than
196
+ // doing a cascade of `if` statements with the `ts.is<NodeType>` functions, since `tree.kind` is
197
+ // effectively integers, and this switch statement is hence optimizable to a jump table. This is
198
+ // a VERY significant enhancement to the debugging experience, too.
199
+ switch (tree.kind) {
200
+ case ts.SyntaxKind.EmptyStatement:
201
+ // Additional semicolon where it doesn't belong.
202
+ return o_tree_1.NO_SYNTAX;
203
+ case ts.SyntaxKind.SourceFile:
204
+ return visitor.sourceFile(tree, this);
205
+ case ts.SyntaxKind.ImportEqualsDeclaration:
206
+ return visitor.importStatement((0, imports_1.analyzeImportEquals)(tree, this), this);
207
+ case ts.SyntaxKind.ImportDeclaration:
208
+ return new o_tree_1.OTree([], (0, imports_1.analyzeImportDeclaration)(tree, this, this.submoduleReferences).map((import_) => visitor.importStatement(import_, this)), { canBreakLine: true, separator: '\n' });
209
+ case ts.SyntaxKind.StringLiteral:
210
+ case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
211
+ return visitor.stringLiteral(tree, this);
212
+ case ts.SyntaxKind.NumericLiteral:
213
+ return visitor.numericLiteral(tree, this);
214
+ case ts.SyntaxKind.FunctionDeclaration:
215
+ return visitor.functionDeclaration(tree, this);
216
+ case ts.SyntaxKind.Identifier:
217
+ return visitor.identifier(tree, this);
218
+ case ts.SyntaxKind.Block:
219
+ return visitor.block(tree, this);
220
+ case ts.SyntaxKind.Parameter:
221
+ return visitor.parameterDeclaration(tree, this);
222
+ case ts.SyntaxKind.ReturnStatement:
223
+ return visitor.returnStatement(tree, this);
224
+ case ts.SyntaxKind.BinaryExpression:
225
+ return visitor.binaryExpression(tree, this);
226
+ case ts.SyntaxKind.IfStatement:
227
+ return visitor.ifStatement(tree, this);
228
+ case ts.SyntaxKind.PropertyAccessExpression:
229
+ const submoduleReference = this.submoduleReferences?.get(tree);
230
+ return visitor.propertyAccessExpression(tree, this, submoduleReference);
231
+ case ts.SyntaxKind.AwaitExpression:
232
+ return visitor.awaitExpression(tree, this);
233
+ case ts.SyntaxKind.CallExpression:
234
+ return visitor.callExpression(tree, this);
235
+ case ts.SyntaxKind.ExpressionStatement:
236
+ return visitor.expressionStatement(tree, this);
237
+ case ts.SyntaxKind.ObjectLiteralExpression:
238
+ return visitor.objectLiteralExpression(tree, this);
239
+ case ts.SyntaxKind.NewExpression:
240
+ return visitor.newExpression(tree, this);
241
+ case ts.SyntaxKind.PropertyAssignment:
242
+ return visitor.propertyAssignment(tree, this);
243
+ case ts.SyntaxKind.VariableStatement:
244
+ return visitor.variableStatement(tree, this);
245
+ case ts.SyntaxKind.VariableDeclarationList:
246
+ return visitor.variableDeclarationList(tree, this);
247
+ case ts.SyntaxKind.VariableDeclaration:
248
+ return visitor.variableDeclaration(tree, this);
249
+ case ts.SyntaxKind.ArrayLiteralExpression:
250
+ return visitor.arrayLiteralExpression(tree, this);
251
+ case ts.SyntaxKind.ShorthandPropertyAssignment:
252
+ return visitor.shorthandPropertyAssignment(tree, this);
253
+ case ts.SyntaxKind.ForOfStatement:
254
+ return visitor.forOfStatement(tree, this);
255
+ case ts.SyntaxKind.ClassDeclaration:
256
+ return visitor.classDeclaration(tree, this);
257
+ case ts.SyntaxKind.Constructor:
258
+ return visitor.constructorDeclaration(tree, this);
259
+ case ts.SyntaxKind.PropertyDeclaration:
260
+ return visitor.propertyDeclaration(tree, this);
261
+ case ts.SyntaxKind.ComputedPropertyName:
262
+ return visitor.computedPropertyName(tree.expression, this);
263
+ case ts.SyntaxKind.MethodDeclaration:
264
+ return visitor.methodDeclaration(tree, this);
265
+ case ts.SyntaxKind.InterfaceDeclaration:
266
+ return visitor.interfaceDeclaration(tree, this);
267
+ case ts.SyntaxKind.PropertySignature:
268
+ return visitor.propertySignature(tree, this);
269
+ case ts.SyntaxKind.MethodSignature:
270
+ return visitor.methodSignature(tree, this);
271
+ case ts.SyntaxKind.AsExpression:
272
+ return visitor.asExpression(tree, this);
273
+ case ts.SyntaxKind.PrefixUnaryExpression:
274
+ return visitor.prefixUnaryExpression(tree, this);
275
+ case ts.SyntaxKind.SpreadAssignment:
276
+ if (this.textOf(tree) === '...') {
277
+ return visitor.ellipsis(tree, this);
278
+ }
279
+ return visitor.spreadAssignment(tree, this);
280
+ case ts.SyntaxKind.SpreadElement:
281
+ if (this.textOf(tree) === '...') {
282
+ return visitor.ellipsis(tree, this);
283
+ }
284
+ return visitor.spreadElement(tree, this);
285
+ case ts.SyntaxKind.ElementAccessExpression:
286
+ return visitor.elementAccessExpression(tree, this);
287
+ case ts.SyntaxKind.TemplateExpression:
288
+ return visitor.templateExpression(tree, this);
289
+ case ts.SyntaxKind.NonNullExpression:
290
+ return visitor.nonNullExpression(tree, this);
291
+ case ts.SyntaxKind.ParenthesizedExpression:
292
+ return visitor.parenthesizedExpression(tree, this);
293
+ case ts.SyntaxKind.VoidExpression:
294
+ return visitor.maskingVoidExpression(tree, this);
295
+ case ts.SyntaxKind.JSDocComment:
296
+ return visitor.jsDoc(tree, this);
297
+ default:
298
+ if (ts.isToken(tree)) {
299
+ return visitor.token(tree, this);
300
+ }
301
+ this.reportUnsupported(tree, undefined);
337
302
  }
338
- this.reportUnsupported(tree, undefined);
339
303
  if (this.options.bestEffort !== false) {
340
304
  // When doing best-effort conversion and we don't understand the node type, just return the complete text of it as-is
341
305
  return new o_tree_1.OTree([this.textOf(tree)]);
@@ -0,0 +1,13 @@
1
+ import * as ts from 'typescript';
2
+ export declare type SubmoduleReferenceMap = ReadonlyMap<ts.PropertyAccessExpression | ts.LeftHandSideExpression | ts.Identifier | ts.PrivateIdentifier, SubmoduleReference>;
3
+ export declare class SubmoduleReference {
4
+ readonly root: ts.Symbol;
5
+ readonly submoduleChain: ts.LeftHandSideExpression | ts.Identifier | ts.PrivateIdentifier;
6
+ readonly path: readonly ts.Node[];
7
+ static inSourceFile(sourceFile: ts.SourceFile, typeChecker: ts.TypeChecker): SubmoduleReferenceMap;
8
+ private static inNode;
9
+ private constructor();
10
+ get lastNode(): ts.Node;
11
+ toString(): string;
12
+ }
13
+ //# sourceMappingURL=submodule-reference.d.ts.map
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SubmoduleReference = void 0;
4
+ const ts = require("typescript");
5
+ class SubmoduleReference {
6
+ constructor(root, submoduleChain, path) {
7
+ this.root = root;
8
+ this.submoduleChain = submoduleChain;
9
+ this.path = path;
10
+ }
11
+ static inSourceFile(sourceFile, typeChecker) {
12
+ const importDeclarations = sourceFile.statements
13
+ .filter((stmt) => ts.isImportDeclaration(stmt))
14
+ .flatMap((stmt) => importedSymbolsFrom(stmt, sourceFile, typeChecker));
15
+ return SubmoduleReference.inNode(sourceFile, typeChecker, new Set(importDeclarations));
16
+ }
17
+ static inNode(node, typeChecker, importDeclarations, map = new Map()) {
18
+ if (ts.isPropertyAccessExpression(node)) {
19
+ const [head, ...tail] = propertyPath(node);
20
+ const symbol = typeChecker.getSymbolAtLocation(head.name);
21
+ if (symbol && importDeclarations.has(symbol)) {
22
+ // This is a reference within an imported namespace, so we need to record that...
23
+ const firstNonNamespace = tail.findIndex((item) => !isLikelyNamespace(item.name, typeChecker));
24
+ if (firstNonNamespace < 0) {
25
+ map.set(node.expression, new SubmoduleReference(symbol, node.expression, []));
26
+ }
27
+ else {
28
+ const tailEnd = tail[firstNonNamespace].expression;
29
+ const path = tail.slice(0, firstNonNamespace).map((item) => item.name);
30
+ map.set(tailEnd, new SubmoduleReference(symbol, tailEnd, path));
31
+ }
32
+ }
33
+ return map;
34
+ }
35
+ // Faster than ||-ing a bung of if statements to avoid traversing uninteresting nodes...
36
+ switch (node.kind) {
37
+ case ts.SyntaxKind.ImportDeclaration:
38
+ case ts.SyntaxKind.ExportDeclaration:
39
+ break;
40
+ default:
41
+ for (const child of node.getChildren()) {
42
+ map = SubmoduleReference.inNode(child, typeChecker, importDeclarations, map);
43
+ }
44
+ }
45
+ return map;
46
+ }
47
+ get lastNode() {
48
+ if (this.path.length === 0) {
49
+ const node = this.root.valueDeclaration ?? this.root.declarations[0];
50
+ return ts.isNamespaceImport(node) || ts.isImportSpecifier(node) ? node.name : node;
51
+ }
52
+ return this.path[this.path.length - 1];
53
+ }
54
+ toString() {
55
+ return `${this.constructor.name}<root=${this.root.name}, path=${JSON.stringify(this.path.map((item) => item.getText(item.getSourceFile())))}>`;
56
+ }
57
+ }
58
+ exports.SubmoduleReference = SubmoduleReference;
59
+ /**
60
+ * Determines what symbols are imported by the given TypeScript import
61
+ * delcaration, in the context of the specified file, using the provided type
62
+ * checker.
63
+ *
64
+ * @param decl an import declaration.
65
+ * @param sourceFile the source file that contains the import declaration.
66
+ * @param typeChecker a TypeChecker instance valid for the provided source file.
67
+ *
68
+ * @returns the (possibly empty) list of symbols imported by this declaration.
69
+ */
70
+ function importedSymbolsFrom(decl, sourceFile, typeChecker) {
71
+ const { importClause } = decl;
72
+ if (importClause == null) {
73
+ // This is a "for side effects" import, which isn't relevant for our business here...
74
+ return [];
75
+ }
76
+ const { name, namedBindings } = importClause;
77
+ const imports = new Array();
78
+ if (name != null) {
79
+ const symbol = typeChecker.getSymbolAtLocation(name);
80
+ if (symbol == null) {
81
+ throw new Error(`No symbol was defined for node ${name.getText(sourceFile)}`);
82
+ }
83
+ imports.push(symbol);
84
+ }
85
+ if (namedBindings != null) {
86
+ if (ts.isNamespaceImport(namedBindings)) {
87
+ const { name } = namedBindings;
88
+ const symbol = typeChecker.getSymbolAtLocation(name);
89
+ if (symbol == null) {
90
+ throw new Error(`No symbol was defined for node ${name.getText(sourceFile)}`);
91
+ }
92
+ imports.push(symbol);
93
+ }
94
+ else {
95
+ for (const specifier of namedBindings.elements) {
96
+ const { name } = specifier;
97
+ const symbol = typeChecker.getSymbolAtLocation(name);
98
+ if (symbol == null) {
99
+ throw new Error(`No symbol was defined for node ${name.getText(sourceFile)}`);
100
+ }
101
+ imports.push(symbol);
102
+ }
103
+ }
104
+ }
105
+ return imports;
106
+ }
107
+ function propertyPath(node) {
108
+ const { expression, name } = node;
109
+ if (!ts.isPropertyAccessExpression(expression)) {
110
+ return [
111
+ { name: expression, expression },
112
+ { name, expression },
113
+ ];
114
+ }
115
+ return [...propertyPath(expression), { name, expression }];
116
+ }
117
+ /**
118
+ * A heuristic to determine whether the provided node likely refers to some
119
+ * namespace.
120
+ *
121
+ * @param node the node to be checked.
122
+ * @param typeChecker a type checker that can obtain symbols for this node.
123
+ *
124
+ * @returns true if the node likely refers to a namespace name.
125
+ */
126
+ function isLikelyNamespace(node, typeChecker) {
127
+ if (!ts.isIdentifier(node)) {
128
+ return false;
129
+ }
130
+ // If the identifier was bound to a symbol, we can inspect the declarations of
131
+ // it to validate they are all module or namespace declarations.
132
+ const symbol = typeChecker.getSymbolAtLocation(node);
133
+ if (symbol != null) {
134
+ return (symbol.declarations.length > 0 &&
135
+ symbol.declarations.every((decl) => ts.isModuleDeclaration(decl) || ts.isNamespaceExport(decl) || ts.isNamespaceImport(decl)));
136
+ }
137
+ // We understand this is likely a namespace if the name does not start with
138
+ // upper-case letter.
139
+ return !startsWithUpperCase(node.text);
140
+ }
141
+ function startsWithUpperCase(text) {
142
+ return text.length > 0 && text[0] === text[0].toUpperCase();
143
+ }
144
+ //# sourceMappingURL=submodule-reference.js.map
@@ -81,6 +81,7 @@ export declare class SnippetTranslator {
81
81
  private readonly visibleSpans;
82
82
  private readonly compilation;
83
83
  private readonly tryCompile;
84
+ private readonly submoduleReferences;
84
85
  constructor(snippet: TypeScriptSnippet, options?: SnippetTranslatorOptions);
85
86
  /**
86
87
  * Returns a boolean if compilation was attempted, and undefined if it was not.
package/lib/translate.js CHANGED
@@ -11,10 +11,12 @@ const ts = require("typescript");
11
11
  const util_1 = require("util");
12
12
  const languages_1 = require("./languages");
13
13
  const record_references_1 = require("./languages/record-references");
14
+ const target_language_1 = require("./languages/target-language");
14
15
  const logging = require("./logging");
15
16
  const o_tree_1 = require("./o-tree");
16
17
  const renderer_1 = require("./renderer");
17
18
  const snippet_1 = require("./snippet");
19
+ const submodule_reference_1 = require("./submodule-reference");
18
20
  const key_1 = require("./tablets/key");
19
21
  const schema_1 = require("./tablets/schema");
20
22
  const tablets_1 = require("./tablets/tablets");
@@ -47,10 +49,14 @@ class Translator {
47
49
  translate(snip, languages = Object.values(languages_1.TargetLanguage)) {
48
50
  logging.debug(`Translating ${(0, key_1.snippetKey)(snip)} ${(0, util_1.inspect)(snip.parameters ?? {})}`);
49
51
  const translator = this.translatorFor(snip);
50
- const translations = (0, util_2.mkDict)(languages.map((lang) => {
52
+ const translations = (0, util_2.mkDict)(languages.flatMap((lang, idx, languages) => {
53
+ if (languages.slice(0, idx).includes(lang)) {
54
+ // This language was duplicated in the request... we'll skip that here...
55
+ return [];
56
+ }
51
57
  const languageConverterFactory = languages_1.TARGET_LANGUAGES[lang];
52
58
  const translated = translator.renderUsing(languageConverterFactory.createVisitor());
53
- return [lang, { source: translated, version: languageConverterFactory.version }];
59
+ return [[lang, { source: translated, version: languageConverterFactory.version }]];
54
60
  }));
55
61
  if (snip.parameters?.infused === undefined) {
56
62
  __classPrivateFieldGet(this, _Translator_diagnostics, "f").push(...translator.diagnostics);
@@ -105,6 +111,8 @@ class SnippetTranslator {
105
111
  this.compilation = compiler.compileInMemory(removeSlashes((0, snippet_1.formatLocation)(snippet.location)), source, fakeCurrentDirectory);
106
112
  // Respect '/// !hide' and '/// !show' directives
107
113
  this.visibleSpans = visible_spans_1.Spans.visibleSpansFromSource(source);
114
+ // Find submodule references on explicit imports
115
+ this.submoduleReferences = submodule_reference_1.SubmoduleReference.inSourceFile(this.compilation.rootFile, this.compilation.program.getTypeChecker());
108
116
  // This makes it about 5x slower, so only do it on demand
109
117
  // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
110
118
  this.tryCompile = (options.includeCompilerDiagnostics || snippet.strict) ?? false;
@@ -150,7 +158,9 @@ class SnippetTranslator {
150
158
  return this.tryCompile ? this.compileDiagnostics.length === 0 : undefined;
151
159
  }
152
160
  renderUsing(visitor) {
153
- const converter = new renderer_1.AstRenderer(this.compilation.rootFile, this.compilation.program.getTypeChecker(), visitor, this.options);
161
+ const converter = new renderer_1.AstRenderer(this.compilation.rootFile, this.compilation.program.getTypeChecker(), visitor, this.options,
162
+ // If we support transitive submodule access, don't provide a submodule reference map.
163
+ (0, target_language_1.supportsTransitiveSubmoduleAccess)(visitor.language) ? undefined : this.submoduleReferences);
154
164
  const converted = converter.convert(this.compilation.rootFile);
155
165
  this.translateDiagnostics.push(...filterVisibleDiagnostics(converter.diagnostics, this.visibleSpans));
156
166
  return (0, o_tree_1.renderTree)(converted, { indentChar: visitor.indentChar, visibleSpans: this.visibleSpans });
@@ -161,7 +171,7 @@ class SnippetTranslator {
161
171
  }
162
172
  fqnsReferenced() {
163
173
  const visitor = new record_references_1.RecordReferencesVisitor(this.visibleSpans);
164
- const converter = new renderer_1.AstRenderer(this.compilation.rootFile, this.compilation.program.getTypeChecker(), visitor, this.options);
174
+ const converter = new renderer_1.AstRenderer(this.compilation.rootFile, this.compilation.program.getTypeChecker(), visitor, this.options, this.submoduleReferences);
165
175
  converter.convert(this.compilation.rootFile);
166
176
  return visitor.fqnsReferenced();
167
177
  }
@@ -1,6 +1,7 @@
1
1
  import * as ts from 'typescript';
2
2
  import { JsiiSymbol } from '../jsii/jsii-utils';
3
3
  import { AstRenderer } from '../renderer';
4
+ import { SubmoduleReferenceMap } from '../submodule-reference';
4
5
  /**
5
6
  * Our own unification of import statements
6
7
  */
@@ -12,7 +13,16 @@ export interface ImportStatement {
12
13
  }
13
14
  export declare type FullImport = {
14
15
  readonly import: 'full';
15
- readonly alias: string;
16
+ /**
17
+ * The name of the namespace prefix in the source code. Used to strip the
18
+ * prefix in certain languages (e.g: Java).
19
+ */
20
+ readonly sourceName: string;
21
+ /**
22
+ * The name under which this module is imported. Undefined if the module is
23
+ * not aliased (could be the case for namepsace/submodule imports).
24
+ */
25
+ readonly alias?: string;
16
26
  };
17
27
  export declare type SelectiveImport = {
18
28
  readonly import: 'selective';
@@ -28,4 +38,5 @@ export interface ImportBinding {
28
38
  }
29
39
  export declare function analyzeImportEquals(node: ts.ImportEqualsDeclaration, context: AstRenderer<any>): ImportStatement;
30
40
  export declare function analyzeImportDeclaration(node: ts.ImportDeclaration, context: AstRenderer<any>): ImportStatement;
41
+ export declare function analyzeImportDeclaration(node: ts.ImportDeclaration, context: AstRenderer<any>, submoduleReferences: SubmoduleReferenceMap): ImportStatement[];
31
42
  //# sourceMappingURL=imports.d.ts.map