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
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
24 changes: 23 additions & 1 deletion 24 src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36046,9 +36046,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,
Comment thread
weswigham marked this conversation as resolved.
Outdated
};

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) {
Comment thread
weswigham marked this conversation as resolved.
Outdated
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;
}
Expand Down
1 change: 1 addition & 0 deletions 1 src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@ namespace ts {
getSymbolOfExternalModuleSpecifier: notImplemented,
isBindingCapturedByNode: notImplemented,
getDeclarationStatementsForSourceFile: notImplemented,
isImportRequiredByAugmentation: notImplemented,
};

/*@internal*/
Expand Down
10 changes: 10 additions & 0 deletions 10 src/compiler/transformers/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
1 change: 1 addition & 0 deletions 1 src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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)

Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -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);
Morty Proxy This is a proxified and sanitized view of the page, visit original site.