Skip to content

Commit

Permalink
feat(25758): Computed properties no throws if there is a duplicate (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
a-tarasyuk authored Mar 20, 2023
1 parent 1ed06e6 commit 9e1f0ad
Show file tree
Hide file tree
Showing 16 changed files with 675 additions and 59 deletions.
53 changes: 29 additions & 24 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25313,32 +25313,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

function tryGetElementAccessExpressionName(node: ElementAccessExpression) {
if (isStringOrNumericLiteralLike(node.argumentExpression)) {
return escapeLeadingUnderscores(node.argumentExpression.text);
}
if (isEntityNameExpression(node.argumentExpression)) {
const symbol = resolveEntityName(node.argumentExpression, SymbolFlags.Value, /*ignoreErrors*/ true);
if (!symbol || !(isConstVariable(symbol) || (symbol.flags & SymbolFlags.EnumMember))) return undefined;
return isStringOrNumericLiteralLike(node.argumentExpression) ? escapeLeadingUnderscores(node.argumentExpression.text) :
isEntityNameExpression(node.argumentExpression) ? tryGetNameFromEntityNameExpression(node.argumentExpression) : undefined;
}

const declaration = symbol.valueDeclaration;
if (declaration === undefined) return undefined;
function tryGetNameFromEntityNameExpression(node: EntityNameOrEntityNameExpression) {
const symbol = resolveEntityName(node, SymbolFlags.Value, /*ignoreErrors*/ true);
if (!symbol || !(isConstVariable(symbol) || (symbol.flags & SymbolFlags.EnumMember))) return undefined;

const type = tryGetTypeFromEffectiveTypeNode(declaration);
if (type) {
const name = tryGetNameFromType(type);
if (name !== undefined) {
return name;
}
}
const declaration = symbol.valueDeclaration;
if (declaration === undefined) return undefined;

if (hasOnlyExpressionInitializer(declaration) && isBlockScopedNameDeclaredBeforeUse(declaration, node.argumentExpression)) {
const initializer = getEffectiveInitializer(declaration);
if (initializer) {
return tryGetNameFromType(getTypeOfExpression(initializer));
}
if (isEnumMember(declaration)) {
return getTextOfPropertyName(declaration.name);
}
const type = tryGetTypeFromEffectiveTypeNode(declaration);
if (type) {
const name = tryGetNameFromType(type);
if (name !== undefined) {
return name;
}
}
if (hasOnlyExpressionInitializer(declaration) && isBlockScopedNameDeclaredBeforeUse(declaration, node)) {
const initializer = getEffectiveInitializer(declaration);
if (initializer) {
return tryGetNameFromType(getTypeOfExpression(initializer));
}
if (isEnumMember(declaration)) {
return getTextOfPropertyName(declaration.name);
}
}
return undefined;
Expand Down Expand Up @@ -47666,7 +47665,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

if (!inDestructuring) {
const effectiveName = getPropertyNameForPropertyNameNode(name);
const effectiveName = getEffectivePropertyNameForPropertyNameNode(name);
if (effectiveName === undefined) {
continue;
}
Expand Down Expand Up @@ -48688,6 +48687,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
return undefined;
}

function getEffectivePropertyNameForPropertyNameNode(node: PropertyName) {
const name = getPropertyNameForPropertyNameNode(node);
return name ? name :
isComputedPropertyName(node) && isEntityNameExpression(node.expression) ? tryGetNameFromEntityNameExpression(node.expression) : undefined;
}
}

function isNotAccessor(declaration: Declaration): boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
tests/cases/compiler/duplicateObjectLiteralProperty_computedName.ts(3,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName.ts(8,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName.ts(13,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName.ts(23,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName.ts(28,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName.ts(33,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName1.ts(3,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName1.ts(8,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName1.ts(13,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName1.ts(23,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName1.ts(28,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName1.ts(33,5): error TS1117: An object literal cannot have multiple properties with the same name.


==== tests/cases/compiler/duplicateObjectLiteralProperty_computedName.ts (6 errors) ====
==== tests/cases/compiler/duplicateObjectLiteralProperty_computedName1.ts (6 errors) ====
const t1 = {
1: 1,
[1]: 0 // duplicate
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//// [duplicateObjectLiteralProperty_computedName.ts]
//// [duplicateObjectLiteralProperty_computedName1.ts]
const t1 = {
1: 1,
[1]: 0 // duplicate
Expand Down Expand Up @@ -35,7 +35,7 @@ const t7 = {
}


//// [duplicateObjectLiteralProperty_computedName.js]
//// [duplicateObjectLiteralProperty_computedName1.js]
var _a, _b, _c, _d, _e, _f, _g;
var t1 = (_a = {
1: 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,74 +1,74 @@
=== tests/cases/compiler/duplicateObjectLiteralProperty_computedName.ts ===
=== tests/cases/compiler/duplicateObjectLiteralProperty_computedName1.ts ===
const t1 = {
>t1 : Symbol(t1, Decl(duplicateObjectLiteralProperty_computedName.ts, 0, 5))
>t1 : Symbol(t1, Decl(duplicateObjectLiteralProperty_computedName1.ts, 0, 5))

1: 1,
>1 : Symbol(1, Decl(duplicateObjectLiteralProperty_computedName.ts, 0, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 1, 9))
>1 : Symbol(1, Decl(duplicateObjectLiteralProperty_computedName1.ts, 0, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 1, 9))

[1]: 0 // duplicate
>[1] : Symbol(1, Decl(duplicateObjectLiteralProperty_computedName.ts, 0, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 1, 9))
>1 : Symbol(1, Decl(duplicateObjectLiteralProperty_computedName.ts, 0, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 1, 9))
>[1] : Symbol(1, Decl(duplicateObjectLiteralProperty_computedName1.ts, 0, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 1, 9))
>1 : Symbol(1, Decl(duplicateObjectLiteralProperty_computedName1.ts, 0, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 1, 9))
}

const t2 = {
>t2 : Symbol(t2, Decl(duplicateObjectLiteralProperty_computedName.ts, 5, 5))
>t2 : Symbol(t2, Decl(duplicateObjectLiteralProperty_computedName1.ts, 5, 5))

1: 1,
>1 : Symbol(1, Decl(duplicateObjectLiteralProperty_computedName.ts, 5, 12))
>1 : Symbol(1, Decl(duplicateObjectLiteralProperty_computedName1.ts, 5, 12))

[+1]: 0 // duplicate
>[+1] : Symbol([+1], Decl(duplicateObjectLiteralProperty_computedName.ts, 6, 9))
>[+1] : Symbol([+1], Decl(duplicateObjectLiteralProperty_computedName1.ts, 6, 9))
}

const t3 = {
>t3 : Symbol(t3, Decl(duplicateObjectLiteralProperty_computedName.ts, 10, 5))
>t3 : Symbol(t3, Decl(duplicateObjectLiteralProperty_computedName1.ts, 10, 5))

"1": 1,
>"1" : Symbol("1", Decl(duplicateObjectLiteralProperty_computedName.ts, 10, 12))
>"1" : Symbol("1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 10, 12))

[+1]: 0 // duplicate
>[+1] : Symbol([+1], Decl(duplicateObjectLiteralProperty_computedName.ts, 11, 11))
>[+1] : Symbol([+1], Decl(duplicateObjectLiteralProperty_computedName1.ts, 11, 11))
}

const t4 = {
>t4 : Symbol(t4, Decl(duplicateObjectLiteralProperty_computedName.ts, 15, 5))
>t4 : Symbol(t4, Decl(duplicateObjectLiteralProperty_computedName1.ts, 15, 5))

"+1": 1,
>"+1" : Symbol("+1", Decl(duplicateObjectLiteralProperty_computedName.ts, 15, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 16, 12))
>"+1" : Symbol("+1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 15, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 16, 12))

[+1]: 0 // two different keys, "+1", "1"
>[+1] : Symbol("+1", Decl(duplicateObjectLiteralProperty_computedName.ts, 15, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 16, 12))
>[+1] : Symbol("+1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 15, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 16, 12))
}

const t5 = {
>t5 : Symbol(t5, Decl(duplicateObjectLiteralProperty_computedName.ts, 20, 5))
>t5 : Symbol(t5, Decl(duplicateObjectLiteralProperty_computedName1.ts, 20, 5))

"+1": 1,
>"+1" : Symbol("+1", Decl(duplicateObjectLiteralProperty_computedName.ts, 20, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 21, 12))
>"+1" : Symbol("+1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 20, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 21, 12))

["+1"]: 0 // duplicate
>["+1"] : Symbol("+1", Decl(duplicateObjectLiteralProperty_computedName.ts, 20, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 21, 12))
>"+1" : Symbol("+1", Decl(duplicateObjectLiteralProperty_computedName.ts, 20, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 21, 12))
>["+1"] : Symbol("+1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 20, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 21, 12))
>"+1" : Symbol("+1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 20, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 21, 12))
}

const t6 = {
>t6 : Symbol(t6, Decl(duplicateObjectLiteralProperty_computedName.ts, 25, 5))
>t6 : Symbol(t6, Decl(duplicateObjectLiteralProperty_computedName1.ts, 25, 5))

"-1": 1,
>"-1" : Symbol("-1", Decl(duplicateObjectLiteralProperty_computedName.ts, 25, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 26, 12))
>"-1" : Symbol("-1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 25, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 26, 12))

[-1]: 0 // duplicate
>[-1] : Symbol("-1", Decl(duplicateObjectLiteralProperty_computedName.ts, 25, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 26, 12))
>[-1] : Symbol("-1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 25, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 26, 12))
}

const t7 = {
>t7 : Symbol(t7, Decl(duplicateObjectLiteralProperty_computedName.ts, 30, 5))
>t7 : Symbol(t7, Decl(duplicateObjectLiteralProperty_computedName1.ts, 30, 5))

"-1": 1,
>"-1" : Symbol("-1", Decl(duplicateObjectLiteralProperty_computedName.ts, 30, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 31, 12))
>"-1" : Symbol("-1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 30, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 31, 12))

["-1"]: 0 // duplicate
>["-1"] : Symbol("-1", Decl(duplicateObjectLiteralProperty_computedName.ts, 30, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 31, 12))
>"-1" : Symbol("-1", Decl(duplicateObjectLiteralProperty_computedName.ts, 30, 12), Decl(duplicateObjectLiteralProperty_computedName.ts, 31, 12))
>["-1"] : Symbol("-1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 30, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 31, 12))
>"-1" : Symbol("-1", Decl(duplicateObjectLiteralProperty_computedName1.ts, 30, 12), Decl(duplicateObjectLiteralProperty_computedName1.ts, 31, 12))
}

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
=== tests/cases/compiler/duplicateObjectLiteralProperty_computedName.ts ===
=== tests/cases/compiler/duplicateObjectLiteralProperty_computedName1.ts ===
const t1 = {
>t1 : { 1: number; }
>{ 1: 1, [1]: 0 // duplicate} : { 1: number; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
tests/cases/compiler/duplicateObjectLiteralProperty_computedName2.ts(8,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName2.ts(13,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName2.ts(18,5): error TS1117: An object literal cannot have multiple properties with the same name.
tests/cases/compiler/duplicateObjectLiteralProperty_computedName2.ts(23,5): error TS1117: An object literal cannot have multiple properties with the same name.


==== tests/cases/compiler/duplicateObjectLiteralProperty_computedName2.ts (4 errors) ====
const n = 1;
const s = "s";
enum E1 { A = "ENUM_KEY" }
enum E2 { B }

const t1 = {
[n]: 1,
[n]: 1, // duplicate
~~~
!!! error TS1117: An object literal cannot have multiple properties with the same name.
}

const t2 = {
[s]: 1,
[s]: 1, // duplicate
~~~
!!! error TS1117: An object literal cannot have multiple properties with the same name.
}

const t3 = {
[E1.A]: 1,
[E1.A]: 1, // duplicate
~~~~~~
!!! error TS1117: An object literal cannot have multiple properties with the same name.
}

const t4 = {
[E2.B]: 1,
[E2.B]: 1, // duplicate
~~~~~~
!!! error TS1117: An object literal cannot have multiple properties with the same name.
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//// [duplicateObjectLiteralProperty_computedName2.ts]
const n = 1;
const s = "s";
enum E1 { A = "ENUM_KEY" }
enum E2 { B }

const t1 = {
[n]: 1,
[n]: 1, // duplicate
}

const t2 = {
[s]: 1,
[s]: 1, // duplicate
}

const t3 = {
[E1.A]: 1,
[E1.A]: 1, // duplicate
}

const t4 = {
[E2.B]: 1,
[E2.B]: 1, // duplicate
}


//// [duplicateObjectLiteralProperty_computedName2.js]
var _a, _b, _c, _d;
var n = 1;
var s = "s";
var E1;
(function (E1) {
E1["A"] = "ENUM_KEY";
})(E1 || (E1 = {}));
var E2;
(function (E2) {
E2[E2["B"] = 0] = "B";
})(E2 || (E2 = {}));
var t1 = (_a = {},
_a[n] = 1,
_a[n] = 1,
_a);
var t2 = (_b = {},
_b[s] = 1,
_b[s] = 1,
_b);
var t3 = (_c = {},
_c[E1.A] = 1,
_c[E1.A] = 1,
_c);
var t4 = (_d = {},
_d[E2.B] = 1,
_d[E2.B] = 1,
_d);
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
=== tests/cases/compiler/duplicateObjectLiteralProperty_computedName2.ts ===
const n = 1;
>n : Symbol(n, Decl(duplicateObjectLiteralProperty_computedName2.ts, 0, 5))

const s = "s";
>s : Symbol(s, Decl(duplicateObjectLiteralProperty_computedName2.ts, 1, 5))

enum E1 { A = "ENUM_KEY" }
>E1 : Symbol(E1, Decl(duplicateObjectLiteralProperty_computedName2.ts, 1, 14))
>A : Symbol(E1.A, Decl(duplicateObjectLiteralProperty_computedName2.ts, 2, 9))

enum E2 { B }
>E2 : Symbol(E2, Decl(duplicateObjectLiteralProperty_computedName2.ts, 2, 26))
>B : Symbol(E2.B, Decl(duplicateObjectLiteralProperty_computedName2.ts, 3, 9))

const t1 = {
>t1 : Symbol(t1, Decl(duplicateObjectLiteralProperty_computedName2.ts, 5, 5))

[n]: 1,
>[n] : Symbol([n], Decl(duplicateObjectLiteralProperty_computedName2.ts, 5, 12), Decl(duplicateObjectLiteralProperty_computedName2.ts, 6, 11))
>n : Symbol(n, Decl(duplicateObjectLiteralProperty_computedName2.ts, 0, 5))

[n]: 1, // duplicate
>[n] : Symbol([n], Decl(duplicateObjectLiteralProperty_computedName2.ts, 5, 12), Decl(duplicateObjectLiteralProperty_computedName2.ts, 6, 11))
>n : Symbol(n, Decl(duplicateObjectLiteralProperty_computedName2.ts, 0, 5))
}

const t2 = {
>t2 : Symbol(t2, Decl(duplicateObjectLiteralProperty_computedName2.ts, 10, 5))

[s]: 1,
>[s] : Symbol([s], Decl(duplicateObjectLiteralProperty_computedName2.ts, 10, 12), Decl(duplicateObjectLiteralProperty_computedName2.ts, 11, 11))
>s : Symbol(s, Decl(duplicateObjectLiteralProperty_computedName2.ts, 1, 5))

[s]: 1, // duplicate
>[s] : Symbol([s], Decl(duplicateObjectLiteralProperty_computedName2.ts, 10, 12), Decl(duplicateObjectLiteralProperty_computedName2.ts, 11, 11))
>s : Symbol(s, Decl(duplicateObjectLiteralProperty_computedName2.ts, 1, 5))
}

const t3 = {
>t3 : Symbol(t3, Decl(duplicateObjectLiteralProperty_computedName2.ts, 15, 5))

[E1.A]: 1,
>[E1.A] : Symbol([E1.A], Decl(duplicateObjectLiteralProperty_computedName2.ts, 15, 12), Decl(duplicateObjectLiteralProperty_computedName2.ts, 16, 14))
>E1.A : Symbol(E1.A, Decl(duplicateObjectLiteralProperty_computedName2.ts, 2, 9))
>E1 : Symbol(E1, Decl(duplicateObjectLiteralProperty_computedName2.ts, 1, 14))
>A : Symbol(E1.A, Decl(duplicateObjectLiteralProperty_computedName2.ts, 2, 9))

[E1.A]: 1, // duplicate
>[E1.A] : Symbol([E1.A], Decl(duplicateObjectLiteralProperty_computedName2.ts, 15, 12), Decl(duplicateObjectLiteralProperty_computedName2.ts, 16, 14))
>E1.A : Symbol(E1.A, Decl(duplicateObjectLiteralProperty_computedName2.ts, 2, 9))
>E1 : Symbol(E1, Decl(duplicateObjectLiteralProperty_computedName2.ts, 1, 14))
>A : Symbol(E1.A, Decl(duplicateObjectLiteralProperty_computedName2.ts, 2, 9))
}

const t4 = {
>t4 : Symbol(t4, Decl(duplicateObjectLiteralProperty_computedName2.ts, 20, 5))

[E2.B]: 1,
>[E2.B] : Symbol([E2.B], Decl(duplicateObjectLiteralProperty_computedName2.ts, 20, 12), Decl(duplicateObjectLiteralProperty_computedName2.ts, 21, 14))
>E2.B : Symbol(E2.B, Decl(duplicateObjectLiteralProperty_computedName2.ts, 3, 9))
>E2 : Symbol(E2, Decl(duplicateObjectLiteralProperty_computedName2.ts, 2, 26))
>B : Symbol(E2.B, Decl(duplicateObjectLiteralProperty_computedName2.ts, 3, 9))

[E2.B]: 1, // duplicate
>[E2.B] : Symbol([E2.B], Decl(duplicateObjectLiteralProperty_computedName2.ts, 20, 12), Decl(duplicateObjectLiteralProperty_computedName2.ts, 21, 14))
>E2.B : Symbol(E2.B, Decl(duplicateObjectLiteralProperty_computedName2.ts, 3, 9))
>E2 : Symbol(E2, Decl(duplicateObjectLiteralProperty_computedName2.ts, 2, 26))
>B : Symbol(E2.B, Decl(duplicateObjectLiteralProperty_computedName2.ts, 3, 9))
}

Loading

0 comments on commit 9e1f0ad

Please sign in to comment.