Issue an error on cross-file merges we cant emit (#38148)

This commit is contained in:
Wesley Wigham 2020-04-23 19:01:16 -07:00 committed by GitHub
parent d7e437a409
commit 815dc90dc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 149 additions and 2 deletions

View File

@ -6029,14 +6029,19 @@ namespace ts {
serializeAsNamespaceDeclaration(realMembers, localName, modifierFlags, !!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Assignment)));
}
if (length(mergedMembers)) {
const containingFile = getSourceFileOfNode(context.enclosingDeclaration);
const localName = getInternalSymbolName(symbol, symbolName);
const nsBody = createModuleBlock([createExportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createNamedExports(map(filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), s => {
createNamedExports(mapDefined(filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), s => {
const name = unescapeLeadingUnderscores(s.escapedName);
const localName = getInternalSymbolName(s, name);
const aliasDecl = s.declarations && getDeclarationOfAliasSymbol(s);
if (containingFile && (aliasDecl ? containingFile !== getSourceFileOfNode(aliasDecl) : !some(s.declarations, d => getSourceFileOfNode(d) === containingFile))) {
context.tracker?.reportNonlocalAugmentation?.(containingFile, symbol, s);
return undefined;
}
const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true);
includePrivateSymbol(target || s);
const targetName = target ? getInternalSymbolName(target, unescapeLeadingUnderscores(target.escapedName)) : localName;

View File

@ -4388,6 +4388,14 @@
"category": "Error",
"code": 6231
},
"Declaration augments declaration in another file. This cannot be serialized.": {
"category": "Error",
"code": 6232
},
"This is the declaration being augmented. Consider moving the augmenting declaration into the same file.": {
"category": "Error",
"code": 6233
},
"Projects to reference": {
"category": "Message",

View File

@ -76,7 +76,8 @@ namespace ts {
reportLikelyUnsafeImportRequiredError,
moduleResolverHost: host,
trackReferencedAmbientModule,
trackExternalModuleSymbolOfImportTypeNode
trackExternalModuleSymbolOfImportTypeNode,
reportNonlocalAugmentation
};
let errorNameNode: DeclarationName | undefined;
@ -190,6 +191,17 @@ namespace ts {
}
}
function reportNonlocalAugmentation(containingFile: SourceFile, parentSymbol: Symbol, symbol: Symbol) {
const primaryDeclaration = find(parentSymbol.declarations, d => getSourceFileOfNode(d) === containingFile)!;
const augmentingDeclarations = filter(symbol.declarations, d => getSourceFileOfNode(d) !== containingFile);
for (const augmentations of augmentingDeclarations) {
context.addDiagnostic(addRelatedInfo(
createDiagnosticForNode(augmentations, Diagnostics.Declaration_augments_declaration_in_another_file_This_cannot_be_serialized),
createDiagnosticForNode(primaryDeclaration, Diagnostics.This_is_the_declaration_being_augmented_Consider_moving_the_augmenting_declaration_into_the_same_file)
));
}
}
function transformDeclarationsForJS(sourceFile: SourceFile, bundled?: boolean) {
const oldDiag = getSymbolAccessibilityDiagnostic;
getSymbolAccessibilityDiagnostic = (s) => ({

View File

@ -6468,6 +6468,7 @@ namespace ts {
moduleResolverHost?: ModuleSpecifierResolutionHost & { getCommonSourceDirectory(): string };
trackReferencedAmbientModule?(decl: ModuleDeclaration, symbol: Symbol): void;
trackExternalModuleSymbolOfImportTypeNode?(symbol: Symbol): void;
reportNonlocalAugmentation?(containingFile: SourceFile, parentSymbol: Symbol, augmentingSymbol: Symbol): void;
}
export interface TextSpan {

View File

@ -0,0 +1,17 @@
tests/cases/conformance/jsdoc/declarations/index.js(4,1): error TS6232: Declaration augments declaration in another file. This cannot be serialized.
==== tests/cases/conformance/jsdoc/declarations/index.js (1 errors) ====
const m = require("./exporter");
module.exports = m.default;
module.exports.memberName = "thing";
~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS6232: Declaration augments declaration in another file. This cannot be serialized.
!!! related TS6233 /.src/tests/cases/conformance/jsdoc/declarations/exporter.js:1:10: This is the declaration being augmented. Consider moving the augmenting declaration into the same file.
==== tests/cases/conformance/jsdoc/declarations/exporter.js (0 errors) ====
function validate() {}
export default validate;

View File

@ -0,0 +1,28 @@
//// [tests/cases/conformance/jsdoc/declarations/jsDeclarationsCrossfileMerge.ts] ////
//// [index.js]
const m = require("./exporter");
module.exports = m.default;
module.exports.memberName = "thing";
//// [exporter.js]
function validate() {}
export default validate;
//// [exporter.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function validate() { }
exports.default = validate;
//// [index.js]
var m = require("./exporter");
module.exports = m.default;
module.exports.memberName = "thing";
//// [index.d.ts]
declare const _exports: typeof import("./exporter").default;
export = _exports;

View File

@ -0,0 +1,28 @@
=== tests/cases/conformance/jsdoc/declarations/index.js ===
const m = require("./exporter");
>m : Symbol(m, Decl(index.js, 0, 5))
>require : Symbol(require)
>"./exporter" : Symbol("tests/cases/conformance/jsdoc/declarations/exporter", Decl(exporter.js, 0, 0))
module.exports = m.default;
>module.exports : Symbol("tests/cases/conformance/jsdoc/declarations/index", Decl(index.js, 0, 0))
>module : Symbol(export=, Decl(index.js, 0, 32))
>exports : Symbol(export=, Decl(index.js, 0, 32))
>m.default : Symbol(default, Decl(exporter.js, 0, 22))
>m : Symbol(m, Decl(index.js, 0, 5))
>default : Symbol(default, Decl(exporter.js, 0, 22))
module.exports.memberName = "thing";
>module.exports.memberName : Symbol(memberName)
>module.exports : Symbol(memberName, Decl(index.js, 2, 27))
>module : Symbol(module, Decl(index.js, 0, 32))
>exports : Symbol("tests/cases/conformance/jsdoc/declarations/index", Decl(index.js, 0, 0))
>memberName : Symbol(memberName, Decl(index.js, 2, 27))
=== tests/cases/conformance/jsdoc/declarations/exporter.js ===
function validate() {}
>validate : Symbol(validate, Decl(exporter.js, 0, 0))
export default validate;
>validate : Symbol(validate, Decl(exporter.js, 0, 0))

View File

@ -0,0 +1,32 @@
=== tests/cases/conformance/jsdoc/declarations/index.js ===
const m = require("./exporter");
>m : typeof import("tests/cases/conformance/jsdoc/declarations/exporter")
>require("./exporter") : typeof import("tests/cases/conformance/jsdoc/declarations/exporter")
>require : any
>"./exporter" : "./exporter"
module.exports = m.default;
>module.exports = m.default : typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default
>module.exports : typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default
>module : { "\"tests/cases/conformance/jsdoc/declarations/index\"": typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default; }
>exports : typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default
>m.default : { (): void; memberName: string; }
>m : typeof import("tests/cases/conformance/jsdoc/declarations/exporter")
>default : { (): void; memberName: string; }
module.exports.memberName = "thing";
>module.exports.memberName = "thing" : "thing"
>module.exports.memberName : string
>module.exports : typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default
>module : { "\"tests/cases/conformance/jsdoc/declarations/index\"": typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default; }
>exports : typeof import("tests/cases/conformance/jsdoc/declarations/exporter").default
>memberName : string
>"thing" : "thing"
=== tests/cases/conformance/jsdoc/declarations/exporter.js ===
function validate() {}
>validate : typeof validate
export default validate;
>validate : typeof validate

View File

@ -0,0 +1,16 @@
// @allowJs: true
// @checkJs: true
// @target: es5
// @lib: es6
// @outDir: ./out
// @declaration: true
// @filename: index.js
const m = require("./exporter");
module.exports = m.default;
module.exports.memberName = "thing";
// @filename: exporter.js
function validate() {}
export default validate;