Fake up a namespace enclosing declaration when generating expando namespace members (#31971)

* Fake up a namespace enclosing declaration when generating expando namespace members

* Fix #31676
This commit is contained in:
Wesley Wigham 2019-06-20 12:58:16 -07:00 committed by GitHub
parent c39a877a92
commit f2735b5a06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 303 additions and 3 deletions

View File

@ -1036,19 +1036,25 @@ namespace ts {
/*body*/ undefined
));
if (clean && resolver.isExpandoFunctionDeclaration(input)) {
const declarations = mapDefined(resolver.getPropertiesOfContainerFunction(input), p => {
const props = resolver.getPropertiesOfContainerFunction(input);
const fakespace = createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, clean.name || createIdentifier("_default"), createModuleBlock([]), NodeFlags.Namespace);
fakespace.flags ^= NodeFlags.Synthesized; // unset synthesized so it is usable as an enclosing declaration
fakespace.parent = enclosingDeclaration as SourceFile | NamespaceDeclaration;
fakespace.locals = createSymbolTable(props);
fakespace.symbol = props[0].parent!;
const declarations = mapDefined(props, p => {
if (!isPropertyAccessExpression(p.valueDeclaration)) {
return undefined;
}
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration);
const type = resolver.createTypeOfDeclaration(p.valueDeclaration, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker);
const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags, symbolTracker);
getSymbolAccessibilityDiagnostic = oldDiag;
const varDecl = createVariableDeclaration(unescapeLeadingUnderscores(p.escapedName), type, /*initializer*/ undefined);
return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([varDecl]));
});
const namespaceDecl = createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input, isPrivate), input.name!, createModuleBlock(declarations), NodeFlags.Namespace);
if (!hasModifier(clean, ModifierFlags.ExportDefault)) {
if (!hasModifier(clean, ModifierFlags.Default)) {
return [clean, namespaceDecl];
}

View File

@ -0,0 +1,114 @@
//// [tests/cases/compiler/declarationEmitDefaultExportWithStaticAssignment.ts] ////
//// [foo.ts]
export class Foo {}
//// [index1.ts]
import {Foo} from './foo';
export default function Example() {}
Example.Foo = Foo
//// [index2.ts]
import {Foo} from './foo';
export {Foo};
export default function Example() {}
Example.Foo = Foo
//// [index3.ts]
export class Bar {}
export default function Example() {}
Example.Bar = Bar
//// [index4.ts]
function A() { }
function B() { }
export function C() {
return null;
}
C.A = A;
C.B = B;
//// [foo.js]
"use strict";
exports.__esModule = true;
var Foo = /** @class */ (function () {
function Foo() {
}
return Foo;
}());
exports.Foo = Foo;
//// [index1.js]
"use strict";
exports.__esModule = true;
var foo_1 = require("./foo");
function Example() { }
exports["default"] = Example;
Example.Foo = foo_1.Foo;
//// [index2.js]
"use strict";
exports.__esModule = true;
var foo_1 = require("./foo");
exports.Foo = foo_1.Foo;
function Example() { }
exports["default"] = Example;
Example.Foo = foo_1.Foo;
//// [index3.js]
"use strict";
exports.__esModule = true;
var Bar = /** @class */ (function () {
function Bar() {
}
return Bar;
}());
exports.Bar = Bar;
function Example() { }
exports["default"] = Example;
Example.Bar = Bar;
//// [index4.js]
"use strict";
exports.__esModule = true;
function A() { }
function B() { }
function C() {
return null;
}
exports.C = C;
C.A = A;
C.B = B;
//// [foo.d.ts]
export declare class Foo {
}
//// [index1.d.ts]
declare function Example(): void;
declare namespace Example {
var Foo: typeof import("./foo").Foo;
}
export default Example;
//// [index2.d.ts]
import { Foo } from './foo';
export { Foo };
declare function Example(): void;
declare namespace Example {
var Foo: typeof import("./foo").Foo;
}
export default Example;
//// [index3.d.ts]
export declare class Bar {
}
declare function Example(): void;
declare namespace Example {
var Bar: typeof import("./index3").Bar;
}
export default Example;
//// [index4.d.ts]
export declare function C(): any;
export declare namespace C {
var A: () => void;
var B: () => void;
}

View File

@ -0,0 +1,71 @@
=== tests/cases/compiler/foo.ts ===
export class Foo {}
>Foo : Symbol(Foo, Decl(foo.ts, 0, 0))
=== tests/cases/compiler/index1.ts ===
import {Foo} from './foo';
>Foo : Symbol(Foo, Decl(index1.ts, 0, 8))
export default function Example() {}
>Example : Symbol(Example, Decl(index1.ts, 0, 26), Decl(index1.ts, 1, 36))
Example.Foo = Foo
>Example.Foo : Symbol(Example.Foo, Decl(index1.ts, 1, 36))
>Example : Symbol(Example, Decl(index1.ts, 0, 26), Decl(index1.ts, 1, 36))
>Foo : Symbol(Example.Foo, Decl(index1.ts, 1, 36))
>Foo : Symbol(Foo, Decl(index1.ts, 0, 8))
=== tests/cases/compiler/index2.ts ===
import {Foo} from './foo';
>Foo : Symbol(Foo, Decl(index2.ts, 0, 8))
export {Foo};
>Foo : Symbol(Foo, Decl(index2.ts, 1, 8))
export default function Example() {}
>Example : Symbol(Example, Decl(index2.ts, 1, 13), Decl(index2.ts, 2, 36))
Example.Foo = Foo
>Example.Foo : Symbol(Example.Foo, Decl(index2.ts, 2, 36))
>Example : Symbol(Example, Decl(index2.ts, 1, 13), Decl(index2.ts, 2, 36))
>Foo : Symbol(Example.Foo, Decl(index2.ts, 2, 36))
>Foo : Symbol(Foo, Decl(index2.ts, 0, 8))
=== tests/cases/compiler/index3.ts ===
export class Bar {}
>Bar : Symbol(Bar, Decl(index3.ts, 0, 0))
export default function Example() {}
>Example : Symbol(Example, Decl(index3.ts, 0, 19), Decl(index3.ts, 1, 36))
Example.Bar = Bar
>Example.Bar : Symbol(Example.Bar, Decl(index3.ts, 1, 36))
>Example : Symbol(Example, Decl(index3.ts, 0, 19), Decl(index3.ts, 1, 36))
>Bar : Symbol(Example.Bar, Decl(index3.ts, 1, 36))
>Bar : Symbol(Bar, Decl(index3.ts, 0, 0))
=== tests/cases/compiler/index4.ts ===
function A() { }
>A : Symbol(A, Decl(index4.ts, 0, 0))
function B() { }
>B : Symbol(B, Decl(index4.ts, 0, 17))
export function C() {
>C : Symbol(C, Decl(index4.ts, 2, 16), Decl(index4.ts, 6, 1))
return null;
}
C.A = A;
>C.A : Symbol(C.A, Decl(index4.ts, 6, 1))
>C : Symbol(C, Decl(index4.ts, 2, 16), Decl(index4.ts, 6, 1))
>A : Symbol(C.A, Decl(index4.ts, 6, 1))
>A : Symbol(A, Decl(index4.ts, 0, 0))
C.B = B;
>C.B : Symbol(C.B, Decl(index4.ts, 8, 8))
>C : Symbol(C, Decl(index4.ts, 2, 16), Decl(index4.ts, 6, 1))
>B : Symbol(C.B, Decl(index4.ts, 8, 8))
>B : Symbol(B, Decl(index4.ts, 0, 17))

View File

@ -0,0 +1,77 @@
=== tests/cases/compiler/foo.ts ===
export class Foo {}
>Foo : Foo
=== tests/cases/compiler/index1.ts ===
import {Foo} from './foo';
>Foo : typeof Foo
export default function Example() {}
>Example : typeof Example
Example.Foo = Foo
>Example.Foo = Foo : typeof Foo
>Example.Foo : typeof Foo
>Example : typeof Example
>Foo : typeof Foo
>Foo : typeof Foo
=== tests/cases/compiler/index2.ts ===
import {Foo} from './foo';
>Foo : typeof Foo
export {Foo};
>Foo : typeof Foo
export default function Example() {}
>Example : typeof Example
Example.Foo = Foo
>Example.Foo = Foo : typeof Foo
>Example.Foo : typeof Foo
>Example : typeof Example
>Foo : typeof Foo
>Foo : typeof Foo
=== tests/cases/compiler/index3.ts ===
export class Bar {}
>Bar : Bar
export default function Example() {}
>Example : typeof Example
Example.Bar = Bar
>Example.Bar = Bar : typeof Bar
>Example.Bar : typeof Bar
>Example : typeof Example
>Bar : typeof Bar
>Bar : typeof Bar
=== tests/cases/compiler/index4.ts ===
function A() { }
>A : () => void
function B() { }
>B : () => void
export function C() {
>C : typeof C
return null;
>null : null
}
C.A = A;
>C.A = A : () => void
>C.A : () => void
>C : typeof C
>A : () => void
>A : () => void
C.B = B;
>C.B = B : () => void
>C.B : () => void
>C : typeof C
>B : () => void
>B : () => void

View File

@ -0,0 +1,32 @@
// @declaration: true
// @filename: foo.ts
export class Foo {}
// @filename: index1.ts
import {Foo} from './foo';
export default function Example() {}
Example.Foo = Foo
// @filename: index2.ts
import {Foo} from './foo';
export {Foo};
export default function Example() {}
Example.Foo = Foo
// @filename: index3.ts
export class Bar {}
export default function Example() {}
Example.Bar = Bar
// @filename: index4.ts
function A() { }
function B() { }
export function C() {
return null;
}
C.A = A;
C.B = B;