Skip to content
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

Disallow merging for default export declarations #3973

Merged
merged 23 commits into from
Jul 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e2c1696
Added tests.
DanielRosenwasser Jul 16, 2015
17593bf
Accepted baselines.
DanielRosenwasser Jul 16, 2015
b403da3
Removed baselines Ryan forgot to remove.
DanielRosenwasser Jul 16, 2015
3e29289
Minor cleanup.
DanielRosenwasser Jul 16, 2015
89398e6
Added single quotes around the declaration name in an error.
DanielRosenwasser Jul 16, 2015
d0fb339
Accepted baselines.
DanielRosenwasser Jul 16, 2015
90f3153
Renamed tests.
DanielRosenwasser Jul 17, 2015
a38dec0
Renamed/accepted baselines.
DanielRosenwasser Jul 17, 2015
f631a20
Added another test.
DanielRosenwasser Jul 22, 2015
7e46445
Accepted baselines.
DanielRosenwasser Jul 22, 2015
8d5d73e
Take default export spaces into account when checking merged declarat…
DanielRosenwasser Jul 22, 2015
be44bc6
Accepted baselines.
DanielRosenwasser Jul 22, 2015
18e36b8
Add suggestion to error message.
DanielRosenwasser Jul 22, 2015
beff651
Accepted baselines.
DanielRosenwasser Jul 22, 2015
ae68352
Merge remote-tracking branch 'origin/master' into disallowDefaultExpo…
DanielRosenwasser Jul 22, 2015
0f828ca
Accepted baselines.
DanielRosenwasser Jul 22, 2015
cf801ef
Added test.
DanielRosenwasser Jul 27, 2015
b84e407
Accepted baselines.
DanielRosenwasser Jul 27, 2015
bad5919
Addressed CR feedback.
DanielRosenwasser Jul 27, 2015
a8f0491
space -> spaces
DanielRosenwasser Jul 27, 2015
9290201
Added a test.
DanielRosenwasser Jul 27, 2015
157235f
Fixed test message.
DanielRosenwasser Jul 27, 2015
28ce0a1
Accepted baselines.
DanielRosenwasser Jul 27, 2015
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
47 changes: 31 additions & 16 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4363,11 +4363,11 @@ namespace ts {
return getInferredType(context, i);
}
}
return t;
return t;
};

mapper.context = context;
return mapper;
return mapper;
}

function identityMapper(type: Type): Type {
Expand Down Expand Up @@ -10849,9 +10849,6 @@ namespace ts {
return;
}

// Exports should be checked only if enclosing module contains both exported and non exported declarations.
// In case if all declarations are non-exported check is unnecessary.

// if localSymbol is defined on node then node itself is exported - check is required
let symbol = node.localSymbol;
if (!symbol) {
Expand All @@ -10871,27 +10868,45 @@ namespace ts {

// we use SymbolFlags.ExportValue, SymbolFlags.ExportType and SymbolFlags.ExportNamespace
// to denote disjoint declarationSpaces (without making new enum type).
let exportedDeclarationSpaces: SymbolFlags = 0;
let nonExportedDeclarationSpaces: SymbolFlags = 0;
forEach(symbol.declarations, d => {
let exportedDeclarationSpaces = SymbolFlags.None;
let nonExportedDeclarationSpaces = SymbolFlags.None;
let defaultExportedDeclarationSpaces = SymbolFlags.None;
for (let d of symbol.declarations) {
let declarationSpaces = getDeclarationSpaces(d);
if (getEffectiveDeclarationFlags(d, NodeFlags.Export)) {
exportedDeclarationSpaces |= declarationSpaces;
let effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, NodeFlags.Export | NodeFlags.Default);

if (effectiveDeclarationFlags & NodeFlags.Export) {
if (effectiveDeclarationFlags & NodeFlags.Default) {
defaultExportedDeclarationSpaces |= declarationSpaces;
}
else {
exportedDeclarationSpaces |= declarationSpaces;
}
}
else {
nonExportedDeclarationSpaces |= declarationSpaces;
}
});
}

let commonDeclarationSpace = exportedDeclarationSpaces & nonExportedDeclarationSpaces;
// Spaces for anyting not declared a 'default export'.
let nonDefaultExportedDeclarationSpaces = exportedDeclarationSpaces | nonExportedDeclarationSpaces;

let commonDeclarationSpacesForExportsAndLocals = exportedDeclarationSpaces & nonExportedDeclarationSpaces;
let commonDeclarationSpacesForDefaultAndNonDefault = defaultExportedDeclarationSpaces & nonDefaultExportedDeclarationSpaces;

if (commonDeclarationSpace) {
if (commonDeclarationSpacesForExportsAndLocals || commonDeclarationSpacesForDefaultAndNonDefault) {
// declaration spaces for exported and non-exported declarations intersect
forEach(symbol.declarations, d => {
if (getDeclarationSpaces(d) & commonDeclarationSpace) {
for (let d of symbol.declarations) {
let declarationSpaces = getDeclarationSpaces(d);

// Only error on the declarations that conributed to the intersecting spaces.
if (declarationSpaces & commonDeclarationSpacesForDefaultAndNonDefault) {
error(d.name, Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, declarationNameToString(d.name));
}
else if (declarationSpaces & commonDeclarationSpacesForExportsAndLocals) {
error(d.name, Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, declarationNameToString(d.name));
}
});
}
}

function getDeclarationSpaces(d: Declaration): SymbolFlags {
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/diagnosticInformationMap.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ namespace ts {
Multiple_constructor_implementations_are_not_allowed: { code: 2392, category: DiagnosticCategory.Error, key: "Multiple constructor implementations are not allowed." },
Duplicate_function_implementation: { code: 2393, category: DiagnosticCategory.Error, key: "Duplicate function implementation." },
Overload_signature_is_not_compatible_with_function_implementation: { code: 2394, category: DiagnosticCategory.Error, key: "Overload signature is not compatible with function implementation." },
Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local: { code: 2395, category: DiagnosticCategory.Error, key: "Individual declarations in merged declaration {0} must be all exported or all local." },
Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local: { code: 2395, category: DiagnosticCategory.Error, key: "Individual declarations in merged declaration '{0}' must be all exported or all local." },
Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters: { code: 2396, category: DiagnosticCategory.Error, key: "Duplicate identifier 'arguments'. Compiler uses 'arguments' to initialize rest parameters." },
Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference: { code: 2399, category: DiagnosticCategory.Error, key: "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference." },
Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference: { code: 2400, category: DiagnosticCategory.Error, key: "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference." },
Expand Down Expand Up @@ -425,6 +425,7 @@ namespace ts {
JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property: { code: 2607, category: DiagnosticCategory.Error, key: "JSX element class does not support attributes because it does not have a '{0}' property" },
The_global_type_JSX_0_may_not_have_more_than_one_property: { code: 2608, category: DiagnosticCategory.Error, key: "The global type 'JSX.{0}' may not have more than one property" },
Cannot_emit_namespaced_JSX_elements_in_React: { code: 2650, category: DiagnosticCategory.Error, key: "Cannot emit namespaced JSX elements in React" },
Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead: { code: 2651, category: DiagnosticCategory.Error, key: "Merged declaration '{0}' cannot include a default export declaration. Consider adding a separate 'export default {0}' declaration instead." },
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
Expand Down
6 changes: 5 additions & 1 deletion src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,7 @@
"category": "Error",
"code": 2394
},
"Individual declarations in merged declaration {0} must be all exported or all local.": {
"Individual declarations in merged declaration '{0}' must be all exported or all local.": {
"category": "Error",
"code": 2395
},
Expand Down Expand Up @@ -1689,6 +1689,10 @@
"category": "Error",
"code": 2650
},
"Merged declaration '{0}' cannot include a default export declaration. Consider adding a separate 'export default {0}' declaration instead.": {
"category": "Error",
"code": 2651
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
Expand Down
49 changes: 49 additions & 0 deletions tests/baselines/reference/defaultExportsCannotMerge01.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
tests/cases/conformance/es6/modules/m1.ts(2,25): error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
tests/cases/conformance/es6/modules/m1.ts(11,18): error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
tests/cases/conformance/es6/modules/m2.ts(5,8): error TS2304: Cannot find name 'Entity'.
tests/cases/conformance/es6/modules/m2.ts(6,8): error TS2503: Cannot find namespace 'Entity'.
tests/cases/conformance/es6/modules/m2.ts(8,8): error TS2339: Property 'x' does not exist on type '() => number'.
tests/cases/conformance/es6/modules/m2.ts(9,8): error TS2339: Property 'y' does not exist on type '() => number'.


==== tests/cases/conformance/es6/modules/m1.ts (2 errors) ====

export default function Decl() {
~~~~
!!! error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
return 0;
}

export interface Decl {
p1: number;
p2: number;
}

export namespace Decl {
~~~~
!!! error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
export var x = 10;
export var y = 20;

interface I {
}
}

==== tests/cases/conformance/es6/modules/m2.ts (4 errors) ====
import Entity from "m1"

Entity();

var x: Entity;
~~~~~~
!!! error TS2304: Cannot find name 'Entity'.
var y: Entity.I;
~~~~~~
!!! error TS2503: Cannot find namespace 'Entity'.

Entity.x;
~
!!! error TS2339: Property 'x' does not exist on type '() => number'.
Entity.y;
~
!!! error TS2339: Property 'y' does not exist on type '() => number'.
50 changes: 50 additions & 0 deletions tests/baselines/reference/defaultExportsCannotMerge01.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//// [tests/cases/conformance/es6/modules/defaultExportsCannotMerge01.ts] ////

//// [m1.ts]

export default function Decl() {
return 0;
}

export interface Decl {
p1: number;
p2: number;
}

export namespace Decl {
export var x = 10;
export var y = 20;

interface I {
}
}

//// [m2.ts]
import Entity from "m1"

Entity();

var x: Entity;
var y: Entity.I;

Entity.x;
Entity.y;

//// [m1.js]
function Decl() {
return 0;
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = Decl;
var Decl;
(function (Decl) {
Decl.x = 10;
Decl.y = 20;
})(Decl = exports.Decl || (exports.Decl = {}));
//// [m2.js]
var m1_1 = require("m1");
m1_1.default();
var x;
var y;
m1_1.default.x;
m1_1.default.y;
44 changes: 44 additions & 0 deletions tests/baselines/reference/defaultExportsCannotMerge02.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
tests/cases/conformance/es6/modules/m1.ts(2,22): error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
tests/cases/conformance/es6/modules/m1.ts(5,18): error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
tests/cases/conformance/es6/modules/m2.ts(3,1): error TS2348: Value of type 'typeof Decl' is not callable. Did you mean to include 'new'?
tests/cases/conformance/es6/modules/m2.ts(6,8): error TS2503: Cannot find namespace 'Entity'.
tests/cases/conformance/es6/modules/m2.ts(8,13): error TS2339: Property 'p1' does not exist on type 'Decl'.
tests/cases/conformance/es6/modules/m2.ts(8,20): error TS2339: Property 'p2' does not exist on type 'Decl'.


==== tests/cases/conformance/es6/modules/m1.ts (2 errors) ====

export default class Decl {
~~~~
!!! error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
}

export interface Decl {
~~~~
!!! error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
p1: number;
p2: number;
}

export namespace Decl {
interface I {
}
}

==== tests/cases/conformance/es6/modules/m2.ts (4 errors) ====
import Entity from "m1"

Entity();
~~~~~~~~
!!! error TS2348: Value of type 'typeof Decl' is not callable. Did you mean to include 'new'?

var x: Entity;
var y: Entity.I;
~~~~~~
!!! error TS2503: Cannot find namespace 'Entity'.
var z = new Entity();
var sum = z.p1 + z.p2
~~
!!! error TS2339: Property 'p1' does not exist on type 'Decl'.
~~
!!! error TS2339: Property 'p2' does not exist on type 'Decl'.
42 changes: 42 additions & 0 deletions tests/baselines/reference/defaultExportsCannotMerge02.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//// [tests/cases/conformance/es6/modules/defaultExportsCannotMerge02.ts] ////

//// [m1.ts]

export default class Decl {
}

export interface Decl {
p1: number;
p2: number;
}

export namespace Decl {
interface I {
}
}

//// [m2.ts]
import Entity from "m1"

Entity();

var x: Entity;
var y: Entity.I;
var z = new Entity();
var sum = z.p1 + z.p2

//// [m1.js]
var Decl = (function () {
function Decl() {
}
return Decl;
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = Decl;
//// [m2.js]
var m1_1 = require("m1");
m1_1.default();
var x;
var y;
var z = new m1_1.default();
var sum = z.p1 + z.p2;
47 changes: 47 additions & 0 deletions tests/baselines/reference/defaultExportsCannotMerge03.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
tests/cases/conformance/es6/modules/m1.ts(2,22): error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
tests/cases/conformance/es6/modules/m1.ts(5,11): error TS2518: Only an ambient class can be merged with an interface.
tests/cases/conformance/es6/modules/m1.ts(5,11): error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
tests/cases/conformance/es6/modules/m2.ts(3,1): error TS2348: Value of type 'typeof Decl' is not callable. Did you mean to include 'new'?
tests/cases/conformance/es6/modules/m2.ts(6,8): error TS2503: Cannot find namespace 'Entity'.
tests/cases/conformance/es6/modules/m2.ts(8,13): error TS2339: Property 'p1' does not exist on type 'Decl'.
tests/cases/conformance/es6/modules/m2.ts(8,20): error TS2339: Property 'p2' does not exist on type 'Decl'.


==== tests/cases/conformance/es6/modules/m1.ts (3 errors) ====

export default class Decl {
~~~~
!!! error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
}

interface Decl {
~~~~
!!! error TS2518: Only an ambient class can be merged with an interface.
~~~~
!!! error TS2651: Merged declaration 'Decl' cannot include a default export declaration. Consider adding a separate 'export default Decl' declaration instead.
p1: number;
p2: number;
}

namespace Decl {
interface I {
}
}

==== tests/cases/conformance/es6/modules/m2.ts (4 errors) ====
import Entity from "m1"

Entity();
~~~~~~~~
!!! error TS2348: Value of type 'typeof Decl' is not callable. Did you mean to include 'new'?

var x: Entity;
var y: Entity.I;
~~~~~~
!!! error TS2503: Cannot find namespace 'Entity'.
var z = new Entity();
var sum = z.p1 + z.p2
~~
!!! error TS2339: Property 'p1' does not exist on type 'Decl'.
~~
!!! error TS2339: Property 'p2' does not exist on type 'Decl'.
Loading