Skip to content

Serialize (noncontextual) keyword named namespace members with export declarations in both declaration emitters #38982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 107 additions & 73 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

26 changes: 22 additions & 4 deletions src/compiler/transformers/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1180,18 +1180,36 @@ namespace ts {
fakespace.parent = enclosingDeclaration as SourceFile | NamespaceDeclaration;
fakespace.locals = createSymbolTable(props);
fakespace.symbol = props[0].parent!;
const declarations = mapDefined(props, p => {
const exportMappings: [Identifier, string][] = [];
const declarations: (VariableStatement | ExportDeclaration)[] = mapDefined(props, p => {
if (!isPropertyAccessExpression(p.valueDeclaration)) {
return undefined; // TODO GH#33569: Handle element access expressions that created late bound names (rather than silently omitting them)
}
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration);
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 nameStr = unescapeLeadingUnderscores(p.escapedName);
const isNonContextualKeywordName = isStringANonContextualKeyword(nameStr);
const name = isNonContextualKeywordName ? getGeneratedNameForNode(p.valueDeclaration) : createIdentifier(nameStr);
if (isNonContextualKeywordName) {
exportMappings.push([name, nameStr]);
}
const varDecl = createVariableDeclaration(name, type, /*initializer*/ undefined);
return createVariableStatement(isNonContextualKeywordName ? undefined : [createToken(SyntaxKind.ExportKeyword)], createVariableDeclarationList([varDecl]));
});
if (!exportMappings.length) {
forEach(declarations, d => d.modifiers = undefined);
}
else {
declarations.push(createExportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createNamedExports(map(exportMappings, ([gen, exp]) => {
return createExportSpecifier(gen, exp);
}))
));
}
const namespaceDecl = createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input), input.name!, createModuleBlock(declarations), NodeFlags.Namespace);

if (!hasEffectiveModifier(clean, ModifierFlags.Default)) {
return [clean, namespaceDecl];
}
Expand Down
40 changes: 40 additions & 0 deletions tests/baselines/reference/declarationEmitFunctionKeywordProp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//// [declarationEmitFunctionKeywordProp.ts]
function foo() {}
foo.null = true;

function bar() {}
bar.async = true;
bar.normal = false;

function baz() {}
baz.class = true;
baz.normal = false;

//// [declarationEmitFunctionKeywordProp.js]
function foo() { }
foo["null"] = true;
function bar() { }
bar.async = true;
bar.normal = false;
function baz() { }
baz["class"] = true;
baz.normal = false;


//// [declarationEmitFunctionKeywordProp.d.ts]
declare function foo(): void;
declare namespace foo {
var _a: boolean;
export { _a as null };
}
declare function bar(): void;
declare namespace bar {
var async: boolean;
var normal: boolean;
}
declare function baz(): void;
declare namespace baz {
var _a: boolean;
export var normal: boolean;
export { _a as class };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
=== tests/cases/compiler/declarationEmitFunctionKeywordProp.ts ===
function foo() {}
>foo : Symbol(foo, Decl(declarationEmitFunctionKeywordProp.ts, 0, 0), Decl(declarationEmitFunctionKeywordProp.ts, 0, 17))

foo.null = true;
>foo.null : Symbol(foo.null, Decl(declarationEmitFunctionKeywordProp.ts, 0, 17))
>foo : Symbol(foo, Decl(declarationEmitFunctionKeywordProp.ts, 0, 0), Decl(declarationEmitFunctionKeywordProp.ts, 0, 17))
>null : Symbol(foo.null, Decl(declarationEmitFunctionKeywordProp.ts, 0, 17))

function bar() {}
>bar : Symbol(bar, Decl(declarationEmitFunctionKeywordProp.ts, 1, 16), Decl(declarationEmitFunctionKeywordProp.ts, 3, 17), Decl(declarationEmitFunctionKeywordProp.ts, 4, 17))

bar.async = true;
>bar.async : Symbol(bar.async, Decl(declarationEmitFunctionKeywordProp.ts, 3, 17))
>bar : Symbol(bar, Decl(declarationEmitFunctionKeywordProp.ts, 1, 16), Decl(declarationEmitFunctionKeywordProp.ts, 3, 17), Decl(declarationEmitFunctionKeywordProp.ts, 4, 17))
>async : Symbol(bar.async, Decl(declarationEmitFunctionKeywordProp.ts, 3, 17))

bar.normal = false;
>bar.normal : Symbol(bar.normal, Decl(declarationEmitFunctionKeywordProp.ts, 4, 17))
>bar : Symbol(bar, Decl(declarationEmitFunctionKeywordProp.ts, 1, 16), Decl(declarationEmitFunctionKeywordProp.ts, 3, 17), Decl(declarationEmitFunctionKeywordProp.ts, 4, 17))
>normal : Symbol(bar.normal, Decl(declarationEmitFunctionKeywordProp.ts, 4, 17))

function baz() {}
>baz : Symbol(baz, Decl(declarationEmitFunctionKeywordProp.ts, 5, 19), Decl(declarationEmitFunctionKeywordProp.ts, 7, 17), Decl(declarationEmitFunctionKeywordProp.ts, 8, 17))

baz.class = true;
>baz.class : Symbol(baz.class, Decl(declarationEmitFunctionKeywordProp.ts, 7, 17))
>baz : Symbol(baz, Decl(declarationEmitFunctionKeywordProp.ts, 5, 19), Decl(declarationEmitFunctionKeywordProp.ts, 7, 17), Decl(declarationEmitFunctionKeywordProp.ts, 8, 17))
>class : Symbol(baz.class, Decl(declarationEmitFunctionKeywordProp.ts, 7, 17))

baz.normal = false;
>baz.normal : Symbol(baz.normal, Decl(declarationEmitFunctionKeywordProp.ts, 8, 17))
>baz : Symbol(baz, Decl(declarationEmitFunctionKeywordProp.ts, 5, 19), Decl(declarationEmitFunctionKeywordProp.ts, 7, 17), Decl(declarationEmitFunctionKeywordProp.ts, 8, 17))
>normal : Symbol(baz.normal, Decl(declarationEmitFunctionKeywordProp.ts, 8, 17))

45 changes: 45 additions & 0 deletions tests/baselines/reference/declarationEmitFunctionKeywordProp.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
=== tests/cases/compiler/declarationEmitFunctionKeywordProp.ts ===
function foo() {}
>foo : typeof foo

foo.null = true;
>foo.null = true : true
>foo.null : boolean
>foo : typeof foo
>null : boolean
>true : true

function bar() {}
>bar : typeof bar

bar.async = true;
>bar.async = true : true
>bar.async : boolean
>bar : typeof bar
>async : boolean
>true : true

bar.normal = false;
>bar.normal = false : false
>bar.normal : boolean
>bar : typeof bar
>normal : boolean
>false : false

function baz() {}
>baz : typeof baz

baz.class = true;
>baz.class = true : true
>baz.class : boolean
>baz : typeof baz
>class : boolean
>true : true

baz.normal = false;
>baz.normal = false : false
>baz.normal : boolean
>baz : typeof baz
>normal : boolean
>false : false

Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ declare namespace Foo {
export { Strings };
}
declare namespace Strings {
export const a: string;
export const b: string;
const a: string;
const b: string;
}
4 changes: 2 additions & 2 deletions tests/baselines/reference/jsDeclarationsClassStatic.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ declare namespace Handler {
}
declare function statische(): void;
declare namespace Strings {
export const a: string;
export const b: string;
const a: string;
const b: string;
}
type HandlerOptions = {
/**
Expand Down
18 changes: 9 additions & 9 deletions tests/baselines/reference/jsDeclarationsEnumTag.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,19 @@ export function consume(t: Target, s: Second, f: Fs): void;
export function ff(s: string): any;
export type Target = string;
export namespace Target {
export const START: string;
export const MIDDLE: string;
export const END: string;
export const OK_I_GUESS: number;
const START: string;
const MIDDLE: string;
const END: string;
const OK_I_GUESS: number;
}
export type Second = number;
export namespace Second {
export const OK: number;
export const FINE: number;
const OK: number;
const FINE: number;
}
export type Fs = (arg0: number) => number;
export namespace Fs {
export function ADD1(n: any): any;
export function ID(n: any): any;
export function SUB1(n: any): number;
function ADD1(n: any): any;
function ID(n: any): any;
function SUB1(n: any): number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ module.exports.Strings = Strings;

//// [index.d.ts]
export namespace Strings {
export const a: string;
export const b: string;
const a: string;
const b: string;
}
export declare const thing: string;
export declare const also: string;
export declare namespace desc {
export const item: string;
const item: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ module.exports = {


//// [index.d.ts]
declare const _exports: {
extends: string;
more: {
others: string[];
};
x: number;
};
export = _exports;
export var x: number;
declare const _extends: string;
export declare namespace more {
const others: string[];
}
export { _extends as extends };
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Object.defineProperty(module.exports, "j", { value: function j() { } });
export function a(): void;
export function b(): void;
export namespace b {
export const cat: string;
const cat: string;
}
/**
* @param {number} a
Expand All @@ -139,7 +139,7 @@ export namespace f {
* @template T
* @param {T} a
*/
export function self<T>(a: T): T;
function self<T>(a: T): T;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While working on this, I found a need for the js declaration emitter to automatically add/strip export modifiers from nested namespace members as needed; so the result of this can be seen in some baseline updates like this - since every member of the containing namespace was exported, there was no need to explicitly have the export modifiers. Now they get stripped, consistent with our transform-based declaration emitter.

}
/**
* @param {{x: string}} a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ function foo() {
//// [index.d.ts]
declare function _exports(o: any): any;
declare namespace _exports {
export const methods: any;
const methods: any;
}
export = _exports;
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ declare namespace Foo {
export { Strings };
}
declare namespace Strings {
export const a: string;
export const b: string;
const a: string;
const b: string;
}
41 changes: 41 additions & 0 deletions tests/baselines/reference/jsDeclarationsFunctionKeywordProp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//// [source.js]
function foo() {}
foo.null = true;

function bar() {}
bar.async = true;
bar.normal = false;

function baz() {}
baz.class = true;
baz.normal = false;

//// [source.js]
function foo() { }
foo.null = true;
function bar() { }
bar.async = true;
bar.normal = false;
function baz() { }
baz.class = true;
baz.normal = false;


//// [source.d.ts]
declare function foo(): void;
declare namespace foo {
const _null: boolean;
export { _null as null };
}
declare function bar(): void;
declare namespace bar {
const async: boolean;
const normal: boolean;
}
declare function baz(): void;
declare namespace baz {
const _class: boolean;
export { _class as class };
const normal_1: boolean;
export { normal_1 as normal };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
=== tests/cases/conformance/jsdoc/declarations/source.js ===
function foo() {}
>foo : Symbol(foo, Decl(source.js, 0, 0), Decl(source.js, 0, 17))

foo.null = true;
>foo.null : Symbol(foo.null, Decl(source.js, 0, 17))
>foo : Symbol(foo, Decl(source.js, 0, 0), Decl(source.js, 0, 17))
>null : Symbol(foo.null, Decl(source.js, 0, 17))

function bar() {}
>bar : Symbol(bar, Decl(source.js, 1, 16), Decl(source.js, 3, 17), Decl(source.js, 4, 17))

bar.async = true;
>bar.async : Symbol(bar.async, Decl(source.js, 3, 17))
>bar : Symbol(bar, Decl(source.js, 1, 16), Decl(source.js, 3, 17), Decl(source.js, 4, 17))
>async : Symbol(bar.async, Decl(source.js, 3, 17))

bar.normal = false;
>bar.normal : Symbol(bar.normal, Decl(source.js, 4, 17))
>bar : Symbol(bar, Decl(source.js, 1, 16), Decl(source.js, 3, 17), Decl(source.js, 4, 17))
>normal : Symbol(bar.normal, Decl(source.js, 4, 17))

function baz() {}
>baz : Symbol(baz, Decl(source.js, 5, 19), Decl(source.js, 7, 17), Decl(source.js, 8, 17))

baz.class = true;
>baz.class : Symbol(baz.class, Decl(source.js, 7, 17))
>baz : Symbol(baz, Decl(source.js, 5, 19), Decl(source.js, 7, 17), Decl(source.js, 8, 17))
>class : Symbol(baz.class, Decl(source.js, 7, 17))

baz.normal = false;
>baz.normal : Symbol(baz.normal, Decl(source.js, 8, 17))
>baz : Symbol(baz, Decl(source.js, 5, 19), Decl(source.js, 7, 17), Decl(source.js, 8, 17))
>normal : Symbol(baz.normal, Decl(source.js, 8, 17))

Loading