mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Retain imports in declaration emit if they augment an export of the importing file (#37820)
* Retain imports in declaration emit if they augment an export of the importing file * (sp) * Check that a merge occurs, just because
This commit is contained in:
parent
a8e1ad4e62
commit
141ee01c8c
@ -36118,9 +36118,31 @@ namespace ts {
|
||||
return !node.locals ? [] : nodeBuilder.symbolTableToDeclarationStatements(node.locals, node, flags, tracker, bundled);
|
||||
}
|
||||
return !sym.exports ? [] : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, tracker, bundled);
|
||||
}
|
||||
},
|
||||
isImportRequiredByAugmentation,
|
||||
};
|
||||
|
||||
function isImportRequiredByAugmentation(node: ImportDeclaration) {
|
||||
const file = getSourceFileOfNode(node);
|
||||
if (!file.symbol) return false;
|
||||
const importTarget = getExternalModuleFileFromDeclaration(node);
|
||||
if (!importTarget) return false;
|
||||
if (importTarget === file) return false;
|
||||
const exports = getExportsOfModule(file.symbol);
|
||||
for (const s of arrayFrom(exports.values())) {
|
||||
if (s.mergeId) {
|
||||
const merged = getMergedSymbol(s);
|
||||
for (const d of merged.declarations) {
|
||||
const declFile = getSourceFileOfNode(d);
|
||||
if (declFile === importTarget) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isInHeritageClause(node: PropertyAccessEntityNameExpression) {
|
||||
return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && node.parent.parent && node.parent.parent.kind === SyntaxKind.HeritageClause;
|
||||
}
|
||||
|
||||
@ -664,6 +664,7 @@ namespace ts {
|
||||
getSymbolOfExternalModuleSpecifier: notImplemented,
|
||||
isBindingCapturedByNode: notImplemented,
|
||||
getDeclarationStatementsForSourceFile: notImplemented,
|
||||
isImportRequiredByAugmentation: notImplemented,
|
||||
};
|
||||
|
||||
/*@internal*/
|
||||
|
||||
@ -717,6 +717,16 @@ namespace ts {
|
||||
rewriteModuleSpecifier(decl, decl.moduleSpecifier)
|
||||
);
|
||||
}
|
||||
// Augmentation of export depends on import
|
||||
if (resolver.isImportRequiredByAugmentation(decl)) {
|
||||
return updateImportDeclaration(
|
||||
decl,
|
||||
/*decorators*/ undefined,
|
||||
decl.modifiers,
|
||||
/*importClause*/ undefined,
|
||||
rewriteModuleSpecifier(decl, decl.moduleSpecifier)
|
||||
);
|
||||
}
|
||||
// Nothing visible
|
||||
}
|
||||
|
||||
|
||||
@ -4004,6 +4004,7 @@ namespace ts {
|
||||
getSymbolOfExternalModuleSpecifier(node: StringLiteralLike): Symbol | undefined;
|
||||
isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean;
|
||||
getDeclarationStatementsForSourceFile(node: SourceFile, flags: NodeBuilderFlags, tracker: SymbolTracker, bundled?: boolean): Statement[] | undefined;
|
||||
isImportRequiredByAugmentation(decl: ImportDeclaration): boolean;
|
||||
}
|
||||
|
||||
export const enum SymbolFlags {
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
//// [tests/cases/compiler/declarationEmitForModuleImportingModuleAugmentationRetainsImport.ts] ////
|
||||
|
||||
//// [child1.ts]
|
||||
import { ParentThing } from './parent';
|
||||
|
||||
declare module './parent' {
|
||||
interface ParentThing {
|
||||
add: (a: number, b: number) => number;
|
||||
}
|
||||
}
|
||||
|
||||
export function child1(prototype: ParentThing) {
|
||||
prototype.add = (a: number, b: number) => a + b;
|
||||
}
|
||||
|
||||
//// [parent.ts]
|
||||
import { child1 } from './child1'; // this import should still exist in some form in the output, since it augments this module
|
||||
|
||||
export class ParentThing implements ParentThing {}
|
||||
|
||||
child1(ParentThing.prototype);
|
||||
|
||||
//// [parent.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.ParentThing = void 0;
|
||||
var child1_1 = require("./child1"); // this import should still exist in some form in the output, since it augments this module
|
||||
var ParentThing = /** @class */ (function () {
|
||||
function ParentThing() {
|
||||
}
|
||||
return ParentThing;
|
||||
}());
|
||||
exports.ParentThing = ParentThing;
|
||||
child1_1.child1(ParentThing.prototype);
|
||||
//// [child1.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.child1 = void 0;
|
||||
function child1(prototype) {
|
||||
prototype.add = function (a, b) { return a + b; };
|
||||
}
|
||||
exports.child1 = child1;
|
||||
|
||||
|
||||
//// [parent.d.ts]
|
||||
import './child1';
|
||||
export declare class ParentThing implements ParentThing {
|
||||
}
|
||||
//// [child1.d.ts]
|
||||
import { ParentThing } from './parent';
|
||||
declare module './parent' {
|
||||
interface ParentThing {
|
||||
add: (a: number, b: number) => number;
|
||||
}
|
||||
}
|
||||
export declare function child1(prototype: ParentThing): void;
|
||||
@ -0,0 +1,46 @@
|
||||
=== tests/cases/compiler/child1.ts ===
|
||||
import { ParentThing } from './parent';
|
||||
>ParentThing : Symbol(ParentThing, Decl(child1.ts, 0, 8))
|
||||
|
||||
declare module './parent' {
|
||||
>'./parent' : Symbol("tests/cases/compiler/parent", Decl(parent.ts, 0, 0), Decl(child1.ts, 0, 39))
|
||||
|
||||
interface ParentThing {
|
||||
>ParentThing : Symbol(ParentThing, Decl(parent.ts, 0, 34), Decl(child1.ts, 2, 27))
|
||||
|
||||
add: (a: number, b: number) => number;
|
||||
>add : Symbol(ParentThing.add, Decl(child1.ts, 3, 27))
|
||||
>a : Symbol(a, Decl(child1.ts, 4, 14))
|
||||
>b : Symbol(b, Decl(child1.ts, 4, 24))
|
||||
}
|
||||
}
|
||||
|
||||
export function child1(prototype: ParentThing) {
|
||||
>child1 : Symbol(child1, Decl(child1.ts, 6, 1))
|
||||
>prototype : Symbol(prototype, Decl(child1.ts, 8, 23))
|
||||
>ParentThing : Symbol(ParentThing, Decl(child1.ts, 0, 8))
|
||||
|
||||
prototype.add = (a: number, b: number) => a + b;
|
||||
>prototype.add : Symbol(ParentThing.add, Decl(child1.ts, 3, 27))
|
||||
>prototype : Symbol(prototype, Decl(child1.ts, 8, 23))
|
||||
>add : Symbol(ParentThing.add, Decl(child1.ts, 3, 27))
|
||||
>a : Symbol(a, Decl(child1.ts, 9, 21))
|
||||
>b : Symbol(b, Decl(child1.ts, 9, 31))
|
||||
>a : Symbol(a, Decl(child1.ts, 9, 21))
|
||||
>b : Symbol(b, Decl(child1.ts, 9, 31))
|
||||
}
|
||||
|
||||
=== tests/cases/compiler/parent.ts ===
|
||||
import { child1 } from './child1'; // this import should still exist in some form in the output, since it augments this module
|
||||
>child1 : Symbol(child1, Decl(parent.ts, 0, 8))
|
||||
|
||||
export class ParentThing implements ParentThing {}
|
||||
>ParentThing : Symbol(ParentThing, Decl(parent.ts, 0, 34), Decl(child1.ts, 2, 27))
|
||||
>ParentThing : Symbol(ParentThing, Decl(parent.ts, 0, 34), Decl(child1.ts, 2, 27))
|
||||
|
||||
child1(ParentThing.prototype);
|
||||
>child1 : Symbol(child1, Decl(parent.ts, 0, 8))
|
||||
>ParentThing.prototype : Symbol(ParentThing.prototype)
|
||||
>ParentThing : Symbol(ParentThing, Decl(parent.ts, 0, 34), Decl(child1.ts, 2, 27))
|
||||
>prototype : Symbol(ParentThing.prototype)
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
=== tests/cases/compiler/child1.ts ===
|
||||
import { ParentThing } from './parent';
|
||||
>ParentThing : typeof ParentThing
|
||||
|
||||
declare module './parent' {
|
||||
>'./parent' : typeof import("tests/cases/compiler/parent")
|
||||
|
||||
interface ParentThing {
|
||||
add: (a: number, b: number) => number;
|
||||
>add : (a: number, b: number) => number
|
||||
>a : number
|
||||
>b : number
|
||||
}
|
||||
}
|
||||
|
||||
export function child1(prototype: ParentThing) {
|
||||
>child1 : (prototype: ParentThing) => void
|
||||
>prototype : ParentThing
|
||||
|
||||
prototype.add = (a: number, b: number) => a + b;
|
||||
>prototype.add = (a: number, b: number) => a + b : (a: number, b: number) => number
|
||||
>prototype.add : (a: number, b: number) => number
|
||||
>prototype : ParentThing
|
||||
>add : (a: number, b: number) => number
|
||||
>(a: number, b: number) => a + b : (a: number, b: number) => number
|
||||
>a : number
|
||||
>b : number
|
||||
>a + b : number
|
||||
>a : number
|
||||
>b : number
|
||||
}
|
||||
|
||||
=== tests/cases/compiler/parent.ts ===
|
||||
import { child1 } from './child1'; // this import should still exist in some form in the output, since it augments this module
|
||||
>child1 : (prototype: ParentThing) => void
|
||||
|
||||
export class ParentThing implements ParentThing {}
|
||||
>ParentThing : ParentThing
|
||||
|
||||
child1(ParentThing.prototype);
|
||||
>child1(ParentThing.prototype) : void
|
||||
>child1 : (prototype: ParentThing) => void
|
||||
>ParentThing.prototype : ParentThing
|
||||
>ParentThing : typeof ParentThing
|
||||
>prototype : ParentThing
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
// @declaration: true
|
||||
// @filename: child1.ts
|
||||
import { ParentThing } from './parent';
|
||||
|
||||
declare module './parent' {
|
||||
interface ParentThing {
|
||||
add: (a: number, b: number) => number;
|
||||
}
|
||||
}
|
||||
|
||||
export function child1(prototype: ParentThing) {
|
||||
prototype.add = (a: number, b: number) => a + b;
|
||||
}
|
||||
|
||||
// @filename: parent.ts
|
||||
import { child1 } from './child1'; // this import should still exist in some form in the output, since it augments this module
|
||||
|
||||
export class ParentThing implements ParentThing {}
|
||||
|
||||
child1(ParentThing.prototype);
|
||||
Loading…
x
Reference in New Issue
Block a user