Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 141ee01

Browse filesBrowse files
authored
Retain imports in declaration emit if they augment an export of the importing file (microsoft#37820)
* Retain imports in declaration emit if they augment an export of the importing file * (sp) * Check that a merge occurs, just because
1 parent a8e1ad4 commit 141ee01
Copy full SHA for 141ee01

8 files changed

+203-1Lines changed: 203 additions & 1 deletion
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+23-1Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36118,9 +36118,31 @@ namespace ts {
3611836118
return !node.locals ? [] : nodeBuilder.symbolTableToDeclarationStatements(node.locals, node, flags, tracker, bundled);
3611936119
}
3612036120
return !sym.exports ? [] : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, tracker, bundled);
36121-
}
36121+
},
36122+
isImportRequiredByAugmentation,
3612236123
};
3612336124

36125+
function isImportRequiredByAugmentation(node: ImportDeclaration) {
36126+
const file = getSourceFileOfNode(node);
36127+
if (!file.symbol) return false;
36128+
const importTarget = getExternalModuleFileFromDeclaration(node);
36129+
if (!importTarget) return false;
36130+
if (importTarget === file) return false;
36131+
const exports = getExportsOfModule(file.symbol);
36132+
for (const s of arrayFrom(exports.values())) {
36133+
if (s.mergeId) {
36134+
const merged = getMergedSymbol(s);
36135+
for (const d of merged.declarations) {
36136+
const declFile = getSourceFileOfNode(d);
36137+
if (declFile === importTarget) {
36138+
return true;
36139+
}
36140+
}
36141+
}
36142+
}
36143+
return false;
36144+
}
36145+
3612436146
function isInHeritageClause(node: PropertyAccessEntityNameExpression) {
3612536147
return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && node.parent.parent && node.parent.parent.kind === SyntaxKind.HeritageClause;
3612636148
}
Collapse file

‎src/compiler/emitter.ts‎

Copy file name to clipboardExpand all lines: src/compiler/emitter.ts
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,7 @@ namespace ts {
664664
getSymbolOfExternalModuleSpecifier: notImplemented,
665665
isBindingCapturedByNode: notImplemented,
666666
getDeclarationStatementsForSourceFile: notImplemented,
667+
isImportRequiredByAugmentation: notImplemented,
667668
};
668669

669670
/*@internal*/
Collapse file

‎src/compiler/transformers/declarations.ts‎

Copy file name to clipboardExpand all lines: src/compiler/transformers/declarations.ts
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,16 @@ namespace ts {
717717
rewriteModuleSpecifier(decl, decl.moduleSpecifier)
718718
);
719719
}
720+
// Augmentation of export depends on import
721+
if (resolver.isImportRequiredByAugmentation(decl)) {
722+
return updateImportDeclaration(
723+
decl,
724+
/*decorators*/ undefined,
725+
decl.modifiers,
726+
/*importClause*/ undefined,
727+
rewriteModuleSpecifier(decl, decl.moduleSpecifier)
728+
);
729+
}
720730
// Nothing visible
721731
}
722732

Collapse file

‎src/compiler/types.ts‎

Copy file name to clipboardExpand all lines: src/compiler/types.ts
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4004,6 +4004,7 @@ namespace ts {
40044004
getSymbolOfExternalModuleSpecifier(node: StringLiteralLike): Symbol | undefined;
40054005
isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean;
40064006
getDeclarationStatementsForSourceFile(node: SourceFile, flags: NodeBuilderFlags, tracker: SymbolTracker, bundled?: boolean): Statement[] | undefined;
4007+
isImportRequiredByAugmentation(decl: ImportDeclaration): boolean;
40074008
}
40084009

40094010
export const enum SymbolFlags {
Collapse file
+56Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//// [tests/cases/compiler/declarationEmitForModuleImportingModuleAugmentationRetainsImport.ts] ////
2+
3+
//// [child1.ts]
4+
import { ParentThing } from './parent';
5+
6+
declare module './parent' {
7+
interface ParentThing {
8+
add: (a: number, b: number) => number;
9+
}
10+
}
11+
12+
export function child1(prototype: ParentThing) {
13+
prototype.add = (a: number, b: number) => a + b;
14+
}
15+
16+
//// [parent.ts]
17+
import { child1 } from './child1'; // this import should still exist in some form in the output, since it augments this module
18+
19+
export class ParentThing implements ParentThing {}
20+
21+
child1(ParentThing.prototype);
22+
23+
//// [parent.js]
24+
"use strict";
25+
exports.__esModule = true;
26+
exports.ParentThing = void 0;
27+
var child1_1 = require("./child1"); // this import should still exist in some form in the output, since it augments this module
28+
var ParentThing = /** @class */ (function () {
29+
function ParentThing() {
30+
}
31+
return ParentThing;
32+
}());
33+
exports.ParentThing = ParentThing;
34+
child1_1.child1(ParentThing.prototype);
35+
//// [child1.js]
36+
"use strict";
37+
exports.__esModule = true;
38+
exports.child1 = void 0;
39+
function child1(prototype) {
40+
prototype.add = function (a, b) { return a + b; };
41+
}
42+
exports.child1 = child1;
43+
44+
45+
//// [parent.d.ts]
46+
import './child1';
47+
export declare class ParentThing implements ParentThing {
48+
}
49+
//// [child1.d.ts]
50+
import { ParentThing } from './parent';
51+
declare module './parent' {
52+
interface ParentThing {
53+
add: (a: number, b: number) => number;
54+
}
55+
}
56+
export declare function child1(prototype: ParentThing): void;
Collapse file
+46Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
=== tests/cases/compiler/child1.ts ===
2+
import { ParentThing } from './parent';
3+
>ParentThing : Symbol(ParentThing, Decl(child1.ts, 0, 8))
4+
5+
declare module './parent' {
6+
>'./parent' : Symbol("tests/cases/compiler/parent", Decl(parent.ts, 0, 0), Decl(child1.ts, 0, 39))
7+
8+
interface ParentThing {
9+
>ParentThing : Symbol(ParentThing, Decl(parent.ts, 0, 34), Decl(child1.ts, 2, 27))
10+
11+
add: (a: number, b: number) => number;
12+
>add : Symbol(ParentThing.add, Decl(child1.ts, 3, 27))
13+
>a : Symbol(a, Decl(child1.ts, 4, 14))
14+
>b : Symbol(b, Decl(child1.ts, 4, 24))
15+
}
16+
}
17+
18+
export function child1(prototype: ParentThing) {
19+
>child1 : Symbol(child1, Decl(child1.ts, 6, 1))
20+
>prototype : Symbol(prototype, Decl(child1.ts, 8, 23))
21+
>ParentThing : Symbol(ParentThing, Decl(child1.ts, 0, 8))
22+
23+
prototype.add = (a: number, b: number) => a + b;
24+
>prototype.add : Symbol(ParentThing.add, Decl(child1.ts, 3, 27))
25+
>prototype : Symbol(prototype, Decl(child1.ts, 8, 23))
26+
>add : Symbol(ParentThing.add, Decl(child1.ts, 3, 27))
27+
>a : Symbol(a, Decl(child1.ts, 9, 21))
28+
>b : Symbol(b, Decl(child1.ts, 9, 31))
29+
>a : Symbol(a, Decl(child1.ts, 9, 21))
30+
>b : Symbol(b, Decl(child1.ts, 9, 31))
31+
}
32+
33+
=== tests/cases/compiler/parent.ts ===
34+
import { child1 } from './child1'; // this import should still exist in some form in the output, since it augments this module
35+
>child1 : Symbol(child1, Decl(parent.ts, 0, 8))
36+
37+
export class ParentThing implements ParentThing {}
38+
>ParentThing : Symbol(ParentThing, Decl(parent.ts, 0, 34), Decl(child1.ts, 2, 27))
39+
>ParentThing : Symbol(ParentThing, Decl(parent.ts, 0, 34), Decl(child1.ts, 2, 27))
40+
41+
child1(ParentThing.prototype);
42+
>child1 : Symbol(child1, Decl(parent.ts, 0, 8))
43+
>ParentThing.prototype : Symbol(ParentThing.prototype)
44+
>ParentThing : Symbol(ParentThing, Decl(parent.ts, 0, 34), Decl(child1.ts, 2, 27))
45+
>prototype : Symbol(ParentThing.prototype)
46+
Collapse file
+46Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
=== tests/cases/compiler/child1.ts ===
2+
import { ParentThing } from './parent';
3+
>ParentThing : typeof ParentThing
4+
5+
declare module './parent' {
6+
>'./parent' : typeof import("tests/cases/compiler/parent")
7+
8+
interface ParentThing {
9+
add: (a: number, b: number) => number;
10+
>add : (a: number, b: number) => number
11+
>a : number
12+
>b : number
13+
}
14+
}
15+
16+
export function child1(prototype: ParentThing) {
17+
>child1 : (prototype: ParentThing) => void
18+
>prototype : ParentThing
19+
20+
prototype.add = (a: number, b: number) => a + b;
21+
>prototype.add = (a: number, b: number) => a + b : (a: number, b: number) => number
22+
>prototype.add : (a: number, b: number) => number
23+
>prototype : ParentThing
24+
>add : (a: number, b: number) => number
25+
>(a: number, b: number) => a + b : (a: number, b: number) => number
26+
>a : number
27+
>b : number
28+
>a + b : number
29+
>a : number
30+
>b : number
31+
}
32+
33+
=== tests/cases/compiler/parent.ts ===
34+
import { child1 } from './child1'; // this import should still exist in some form in the output, since it augments this module
35+
>child1 : (prototype: ParentThing) => void
36+
37+
export class ParentThing implements ParentThing {}
38+
>ParentThing : ParentThing
39+
40+
child1(ParentThing.prototype);
41+
>child1(ParentThing.prototype) : void
42+
>child1 : (prototype: ParentThing) => void
43+
>ParentThing.prototype : ParentThing
44+
>ParentThing : typeof ParentThing
45+
>prototype : ParentThing
46+
Collapse file
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// @declaration: true
2+
// @filename: child1.ts
3+
import { ParentThing } from './parent';
4+
5+
declare module './parent' {
6+
interface ParentThing {
7+
add: (a: number, b: number) => number;
8+
}
9+
}
10+
11+
export function child1(prototype: ParentThing) {
12+
prototype.add = (a: number, b: number) => a + b;
13+
}
14+
15+
// @filename: parent.ts
16+
import { child1 } from './child1'; // this import should still exist in some form in the output, since it augments this module
17+
18+
export class ParentThing implements ParentThing {}
19+
20+
child1(ParentThing.prototype);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.