diff --git a/src/linter/ui5Types/amdTranspiler/moduleDeclarationToDefinition.ts b/src/linter/ui5Types/amdTranspiler/moduleDeclarationToDefinition.ts index 1f8960e95..3f4641be6 100644 --- a/src/linter/ui5Types/amdTranspiler/moduleDeclarationToDefinition.ts +++ b/src/linter/ui5Types/amdTranspiler/moduleDeclarationToDefinition.ts @@ -49,7 +49,7 @@ function collectImports( return {imports, identifiers}; } - let factoryParams: ts.Identifier[] | undefined; + let factoryParams: (ts.Identifier | ts.ObjectBindingPattern)[] | undefined; let factoryRequiresCallWrapper = false; if (moduleDeclaration.factory) { if (ts.isFunctionExpression(moduleDeclaration.factory) || @@ -57,13 +57,12 @@ function collectImports( ts.isFunctionDeclaration(moduleDeclaration.factory)) { // Extract parameter names factoryParams = moduleDeclaration.factory.parameters.map((param) => { - if (!ts.isIdentifier(param.name)) { - // Indicates destructuring in factory signature. This is not (yet?) supported - throw new UnsupportedModuleError( - `Unexpected parameter type ${ts.SyntaxKind[param.kind]} ` + - `at ${toPosStr(param)}`); + if (ts.isIdentifier(param.name) || ts.isObjectBindingPattern(param.name)) { + return param.name; + } else { + throw new UnsupportedModuleError(`Unable to determine parameter name for factory. Can't parse ` + + `parameter at ${toPosStr(param)}`); } - return param.name; }); } else if (ts.isIdentifier(moduleDeclaration.factory)) { factoryRequiresCallWrapper = true; @@ -92,20 +91,25 @@ function collectImports( moduleSpecifier = dep; } let identifier: ts.Identifier | undefined; + let namedImports: ts.NamedImports | undefined; if (factoryRequiresCallWrapper) { // Generate variable name based on import module // Later this variable will be used to call the factory function identifier = nodeFactory.createUniqueName(dep.text.replace(/[^a-zA-Z0-9]/g, "_")); } else if (factoryParams?.[i]) { // Use factory parameter identifier as import identifier - identifier = factoryParams[i]; + const factoryParam = factoryParams[i]; + if (ts.isIdentifier(factoryParam)) { + identifier = factoryParam; + } else if (ts.isObjectBindingPattern(factoryParam)) { + namedImports = createNamedImportsFromObjectBindingPattern(factoryParam, nodeFactory); + } } // else: Side effect imports. No identifier needed - let importClause; if (identifier) { identifiers.push(identifier); - importClause = nodeFactory.createImportClause(false, identifier, undefined); } + const importClause = nodeFactory.createImportClause(false, identifier, namedImports); imports.push(nodeFactory.createImportDeclaration( undefined, @@ -343,3 +347,20 @@ function createDefaultExport(factory: ts.NodeFactory, node: ts.Node): ts.Stateme toPosStr(node)); } } + +function createNamedImportsFromObjectBindingPattern( + objectBindingPattern: ts.ObjectBindingPattern, nodeFactory: ts.NodeFactory +): ts.NamedImports { + const elements: ts.ImportSpecifier[] = []; + for (const element of objectBindingPattern.elements) { + if (ts.isBindingElement(element)) { + if (ts.isIdentifier(element.name)) { + elements.push(nodeFactory.createImportSpecifier(false, undefined, element.name)); + } else { + throw new UnsupportedModuleError( + `Unsupported parameter destructuring for factory at ${toPosStr(element.name)}`); + } + } + } + return nodeFactory.createNamedImports(elements); +} diff --git a/test/fixtures/transpiler/amd/Factory_ParameterDestructuring.js b/test/fixtures/transpiler/amd/Factory_ParameterDestructuring.js new file mode 100644 index 000000000..c1900fbcf --- /dev/null +++ b/test/fixtures/transpiler/amd/Factory_ParameterDestructuring.js @@ -0,0 +1,7 @@ +sap.ui.define([ + "sap/ui/core/library" +], function( + {MessageType} +) { + +}); diff --git a/test/lib/linter/amdTranspiler/snapshots/transpiler.ts.md b/test/lib/linter/amdTranspiler/snapshots/transpiler.ts.md index 5fdfff128..44bbf716f 100644 --- a/test/lib/linter/amdTranspiler/snapshots/transpiler.ts.md +++ b/test/lib/linter/amdTranspiler/snapshots/transpiler.ts.md @@ -702,6 +702,26 @@ Generated by [AVA](https://avajs.dev). version: 3, } +## Transpile Factory_ParameterDestructuring.js + +> Snapshot 1 + + `import { MessageType } from "sap/ui/core/library";␊ + //# sourceMappingURL=Factory_ParameterDestructuring.js.map` + +> Snapshot 2 + + { + file: 'Factory_ParameterDestructuring.js', + mappings: 'SAGE,WAAW,QAFZ,qBAAqB', + names: [], + sourceRoot: '', + sources: [ + 'Factory_ParameterDestructuring.js', + ], + version: 3, + } + ## Transpile Factory_ReturnCallExp.js > Snapshot 1 diff --git a/test/lib/linter/amdTranspiler/snapshots/transpiler.ts.snap b/test/lib/linter/amdTranspiler/snapshots/transpiler.ts.snap index 8502be049..62724f023 100644 Binary files a/test/lib/linter/amdTranspiler/snapshots/transpiler.ts.snap and b/test/lib/linter/amdTranspiler/snapshots/transpiler.ts.snap differ