Merge pull request #41190 from weswigham/handle-binding-element-aliases

Handle the new js binding element alias symbols in JS declaration emit
This commit is contained in:
Wesley Wigham
2020-10-23 10:31:08 -07:00
committed by GitHub
5 changed files with 242 additions and 0 deletions

View File

@@ -6783,6 +6783,38 @@ namespace ts {
const targetName = getInternalSymbolName(target, verbatimTargetName);
includePrivateSymbol(target); // the target may be within the same scope - attempt to serialize it first
switch (node.kind) {
case SyntaxKind.BindingElement:
if (node.parent?.parent?.kind === SyntaxKind.VariableDeclaration) {
// const { SomeClass } = require('./lib');
const specifier = getSpecifierForModuleSymbol(target.parent || target, context); // './lib'
const { propertyName } = node as BindingElement;
addResult(factory.createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, factory.createNamedImports([factory.createImportSpecifier(
propertyName && isIdentifier(propertyName) ? factory.createIdentifier(idText(propertyName)) : undefined,
factory.createIdentifier(localName)
)])),
factory.createStringLiteral(specifier)
), ModifierFlags.None);
break;
}
// At present, the below case should be entirely unhit, as, generally speaking, the below case is *usually* bound
// such that the `BinaryExpression` is the declaration rather than the specific, nested binding element
// (because we don't seek to emit an alias in these forms yet). As such, the `BinaryExpression` switch case
// will be what actually handles this form. _However_, in anticipation of binding the below with proper
// alias symbols, I'm _pretty comfortable_ including the case here, even though it is not yet live.
if (node.parent?.parent?.kind === SyntaxKind.BinaryExpression) {
// module.exports = { SomeClass }
serializeExportSpecifier(
unescapeLeadingUnderscores(symbol.escapedName),
targetName
);
break;
}
// We don't know how to serialize this (nested?) binding element
Debug.failBadSyntaxKind(node.parent?.parent || node, "Unhandled binding element grandparent kind in declaration serialization");
break;
case SyntaxKind.VariableDeclaration:
// commonjs require: const x = require('y')
if (isPropertyAccessExpression((node as VariableDeclaration).initializer!)) {

View File

@@ -0,0 +1,67 @@
//// [tests/cases/conformance/jsdoc/declarations/jsDeclarationsReexportedCjsAlias.ts] ////
//// [lib.js]
/**
* @param {string} a
*/
function bar(a) {
return a + a;
}
class SomeClass {
a() {
return 1;
}
}
module.exports = {
bar,
SomeClass
}
//// [main.js]
const { SomeClass, SomeClass: Another } = require('./lib');
module.exports = {
SomeClass,
Another
}
//// [lib.js]
/**
* @param {string} a
*/
function bar(a) {
return a + a;
}
var SomeClass = /** @class */ (function () {
function SomeClass() {
}
SomeClass.prototype.a = function () {
return 1;
};
return SomeClass;
}());
module.exports = {
bar: bar,
SomeClass: SomeClass
};
//// [main.js]
var _a = require('./lib'), SomeClass = _a.SomeClass, Another = _a.SomeClass;
module.exports = {
SomeClass: SomeClass,
Another: Another
};
//// [lib.d.ts]
/**
* @param {string} a
*/
export function bar(a: string): string;
export class SomeClass {
a(): number;
}
//// [main.d.ts]
import { SomeClass } from "./lib";
import { SomeClass as Another } from "./lib";
export { SomeClass, Another };

View File

@@ -0,0 +1,53 @@
=== tests/cases/conformance/jsdoc/declarations/main.js ===
const { SomeClass, SomeClass: Another } = require('./lib');
>SomeClass : Symbol(SomeClass, Decl(main.js, 0, 7))
>SomeClass : Symbol(SomeClass, Decl(lib.js, 14, 8))
>Another : Symbol(Another, Decl(main.js, 0, 18))
>require : Symbol(require)
>'./lib' : Symbol("tests/cases/conformance/jsdoc/declarations/lib", Decl(lib.js, 0, 0))
module.exports = {
>module.exports : Symbol("tests/cases/conformance/jsdoc/declarations/main", Decl(main.js, 0, 0))
>module : Symbol(export=, Decl(main.js, 0, 59))
>exports : Symbol(export=, Decl(main.js, 0, 59))
SomeClass,
>SomeClass : Symbol(SomeClass, Decl(main.js, 2, 18))
Another
>Another : Symbol(Another, Decl(main.js, 3, 14))
}
=== tests/cases/conformance/jsdoc/declarations/lib.js ===
/**
* @param {string} a
*/
function bar(a) {
>bar : Symbol(bar, Decl(lib.js, 0, 0))
>a : Symbol(a, Decl(lib.js, 3, 13))
return a + a;
>a : Symbol(a, Decl(lib.js, 3, 13))
>a : Symbol(a, Decl(lib.js, 3, 13))
}
class SomeClass {
>SomeClass : Symbol(SomeClass, Decl(lib.js, 5, 1))
a() {
>a : Symbol(SomeClass.a, Decl(lib.js, 7, 17))
return 1;
}
}
module.exports = {
>module.exports : Symbol("tests/cases/conformance/jsdoc/declarations/lib", Decl(lib.js, 0, 0))
>module : Symbol(export=, Decl(lib.js, 11, 1))
>exports : Symbol(export=, Decl(lib.js, 11, 1))
bar,
>bar : Symbol(bar, Decl(lib.js, 13, 18))
SomeClass
>SomeClass : Symbol(SomeClass, Decl(lib.js, 14, 8))
}

View File

@@ -0,0 +1,60 @@
=== tests/cases/conformance/jsdoc/declarations/main.js ===
const { SomeClass, SomeClass: Another } = require('./lib');
>SomeClass : typeof SomeClass
>SomeClass : any
>Another : typeof SomeClass
>require('./lib') : { bar: (a: string) => string; SomeClass: typeof SomeClass; }
>require : any
>'./lib' : "./lib"
module.exports = {
>module.exports = { SomeClass, Another} : { SomeClass: typeof SomeClass; Another: typeof SomeClass; }
>module.exports : { SomeClass: typeof SomeClass; Another: typeof SomeClass; }
>module : { "\"tests/cases/conformance/jsdoc/declarations/main\"": { SomeClass: typeof SomeClass; Another: typeof SomeClass; }; }
>exports : { SomeClass: typeof SomeClass; Another: typeof SomeClass; }
>{ SomeClass, Another} : { SomeClass: typeof SomeClass; Another: typeof SomeClass; }
SomeClass,
>SomeClass : typeof SomeClass
Another
>Another : typeof SomeClass
}
=== tests/cases/conformance/jsdoc/declarations/lib.js ===
/**
* @param {string} a
*/
function bar(a) {
>bar : (a: string) => string
>a : string
return a + a;
>a + a : string
>a : string
>a : string
}
class SomeClass {
>SomeClass : SomeClass
a() {
>a : () => number
return 1;
>1 : 1
}
}
module.exports = {
>module.exports = { bar, SomeClass} : { bar: (a: string) => string; SomeClass: typeof SomeClass; }
>module.exports : { bar: (a: string) => string; SomeClass: typeof SomeClass; }
>module : { "\"tests/cases/conformance/jsdoc/declarations/lib\"": { bar: (a: string) => string; SomeClass: typeof SomeClass; }; }
>exports : { bar: (a: string) => string; SomeClass: typeof SomeClass; }
>{ bar, SomeClass} : { bar: (a: string) => string; SomeClass: typeof SomeClass; }
bar,
>bar : (a: string) => string
SomeClass
>SomeClass : typeof SomeClass
}

View File

@@ -0,0 +1,30 @@
// @allowJs: true
// @checkJs: true
// @target: es5
// @outDir: ./out
// @declaration: true
// @filename: lib.js
/**
* @param {string} a
*/
function bar(a) {
return a + a;
}
class SomeClass {
a() {
return 1;
}
}
module.exports = {
bar,
SomeClass
}
// @filename: main.js
const { SomeClass, SomeClass: Another } = require('./lib');
module.exports = {
SomeClass,
Another
}