Skip to content

Commit 6565025

Browse files
Merge pull request #17462 from Microsoft/codeFixForErrorForPropertyOfTypeAsType
Quick fix to correct qualified names to indexed access types
2 parents ce51a09 + c659fe9 commit 6565025

9 files changed

+107
-13
lines changed

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3657,6 +3657,10 @@
36573657
"category": "Message",
36583658
"code": 90025
36593659
},
3660+
"Rewrite as the indexed access type '{0}'.": {
3661+
"category": "Message",
3662+
"code": 90026
3663+
},
36603664

36613665
"Convert function to an ES2015 class": {
36623666
"category": "Message",

src/harness/tsconfig.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,6 @@
7474
"../services/formatting/tokenRange.ts",
7575
"../services/codeFixProvider.ts",
7676
"../services/codefixes/fixes.ts",
77-
"../services/codefixes/fixExtendsInterfaceBecomesImplements.ts",
78-
"../services/codefixes/fixClassIncorrectlyImplementsInterface.ts",
79-
"../services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts",
80-
"../services/codefixes/fixClassSuperMustPrecedeThisAccess.ts",
81-
"../services/codefixes/fixConstructorForDerivedNeedSuperCall.ts",
8277
"../services/codefixes/helpers.ts",
8378
"../services/codefixes/importFixes.ts",
8479
"../services/codefixes/fixUnusedIdentifier.ts",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* @internal */
2+
namespace ts.codefix {
3+
registerCodeFix({
4+
errorCodes: [Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1.code],
5+
getCodeActions: (context: CodeFixContext) => {
6+
const sourceFile = context.sourceFile;
7+
const token = getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false);
8+
const qualifiedName = getAncestor(token, SyntaxKind.QualifiedName) as QualifiedName;
9+
Debug.assert(!!qualifiedName, "Expected position to be owned by a qualified name.");
10+
if (!isIdentifier(qualifiedName.left)) {
11+
return undefined;
12+
}
13+
const leftText = qualifiedName.left.getText(sourceFile);
14+
const rightText = qualifiedName.right.getText(sourceFile);
15+
const replacement = createIndexedAccessTypeNode(
16+
createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined),
17+
createLiteralTypeNode(createLiteral(rightText)));
18+
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
19+
changeTracker.replaceNode(sourceFile, qualifiedName, replacement);
20+
21+
return [{
22+
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Rewrite_as_the_indexed_access_type_0), [`${leftText}["${rightText}"]`]),
23+
changes: changeTracker.getChanges()
24+
}];
25+
}
26+
});
27+
}

src/services/codefixes/fixes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/// <reference path="correctQualifiedNameToIndexedAccessType.ts" />
12
/// <reference path="fixClassIncorrectlyImplementsInterface.ts" />
23
/// <reference path="fixAddMissingMember.ts" />
34
/// <reference path="fixSpelling.ts" />

tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.errors.txt

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(6,12): error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
2-
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(14,12): error TS2503: Cannot find namespace 'Foo'.
3-
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(22,12): error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
4-
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(29,12): error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
5-
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here.
2+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(7,18): error TS2694: Namespace 'Test1' has no exported member 'Foo'.
3+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(15,12): error TS2503: Cannot find namespace 'Foo'.
4+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(16,18): error TS2694: Namespace 'Test2' has no exported member 'Foo'.
5+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(24,12): error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
6+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(25,18): error TS2694: Namespace 'Test3' has no exported member 'Foo'.
7+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(32,12): error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
8+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(33,18): error TS2694: Namespace 'Test4' has no exported member 'Foo'.
9+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(40,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here.
10+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(41,18): error TS2694: Namespace 'Test5' has no exported member 'Foo'.
11+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(44,20): error TS2694: Namespace 'Test5' has no exported member 'Foo'.
12+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(44,24): error TS1003: Identifier expected.
613

714

8-
==== tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts (5 errors) ====
15+
==== tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts (12 errors) ====
916
namespace Test1 {
1017
export interface Foo {
1118
bar: string;
@@ -14,6 +21,9 @@ tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702
1421
var x: Foo.bar = "";
1522
~~~~~~~
1623
!!! error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
24+
var y: Test1.Foo.bar = "";
25+
~~~
26+
!!! error TS2694: Namespace 'Test1' has no exported member 'Foo'.
1727
}
1828

1929
namespace Test2 {
@@ -24,6 +34,9 @@ tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702
2434
var x: Foo.bar = "";
2535
~~~
2636
!!! error TS2503: Cannot find namespace 'Foo'.
37+
var y: Test2.Foo.bar = "";
38+
~~~
39+
!!! error TS2694: Namespace 'Test2' has no exported member 'Foo'.
2740
}
2841

2942
namespace Test3 {
@@ -34,6 +47,9 @@ tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702
3447
var x: Foo.bar = "";
3548
~~~~~~~
3649
!!! error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
50+
var y: Test3.Foo.bar = "";
51+
~~~
52+
!!! error TS2694: Namespace 'Test3' has no exported member 'Foo'.
3753
}
3854

3955
namespace Test4 {
@@ -43,6 +59,9 @@ tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702
4359
var x: Foo.bar = "";
4460
~~~~~~~
4561
!!! error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
62+
var y: Test4.Foo.bar = "";
63+
~~~
64+
!!! error TS2694: Namespace 'Test4' has no exported member 'Foo'.
4665
}
4766

4867
namespace Test5 {
@@ -52,4 +71,13 @@ tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702
5271
var x: Foo.bar = "";
5372
~~~
5473
!!! error TS2702: 'Foo' only refers to a type, but is being used as a namespace here.
55-
}
74+
var y: Test5.Foo.bar = "";
75+
~~~
76+
!!! error TS2694: Namespace 'Test5' has no exported member 'Foo'.
77+
}
78+
79+
import lol = Test5.Foo.
80+
~~~
81+
!!! error TS2694: Namespace 'Test5' has no exported member 'Foo'.
82+
83+
!!! error TS1003: Identifier expected.

tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace Test1 {
55
}
66

77
var x: Foo.bar = "";
8+
var y: Test1.Foo.bar = "";
89
}
910

1011
namespace Test2 {
@@ -13,6 +14,7 @@ namespace Test2 {
1314
}
1415

1516
var x: Foo.bar = "";
17+
var y: Test2.Foo.bar = "";
1618
}
1719

1820
namespace Test3 {
@@ -21,26 +23,32 @@ namespace Test3 {
2123
}
2224

2325
var x: Foo.bar = "";
26+
var y: Test3.Foo.bar = "";
2427
}
2528

2629
namespace Test4 {
2730
export type Foo = { bar: number }
2831
| { bar: string }
2932

3033
var x: Foo.bar = "";
34+
var y: Test4.Foo.bar = "";
3135
}
3236

3337
namespace Test5 {
3438
export type Foo = { bar: number }
3539
| { wat: string }
3640

3741
var x: Foo.bar = "";
38-
}
42+
var y: Test5.Foo.bar = "";
43+
}
44+
45+
import lol = Test5.Foo.
3946

4047
//// [errorForUsingPropertyOfTypeAsType01.js]
4148
var Test1;
4249
(function (Test1) {
4350
var x = "";
51+
var y = "";
4452
})(Test1 || (Test1 = {}));
4553
var Test2;
4654
(function (Test2) {
@@ -51,16 +59,21 @@ var Test2;
5159
}());
5260
Test2.Foo = Foo;
5361
var x = "";
62+
var y = "";
5463
})(Test2 || (Test2 = {}));
5564
var Test3;
5665
(function (Test3) {
5766
var x = "";
67+
var y = "";
5868
})(Test3 || (Test3 = {}));
5969
var Test4;
6070
(function (Test4) {
6171
var x = "";
72+
var y = "";
6273
})(Test4 || (Test4 = {}));
6374
var Test5;
6475
(function (Test5) {
6576
var x = "";
77+
var y = "";
6678
})(Test5 || (Test5 = {}));
79+
var lol = Test5.Foo.;

tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ namespace Test1 {
44
}
55

66
var x: Foo.bar = "";
7+
var y: Test1.Foo.bar = "";
78
}
89

910
namespace Test2 {
@@ -12,6 +13,7 @@ namespace Test2 {
1213
}
1314

1415
var x: Foo.bar = "";
16+
var y: Test2.Foo.bar = "";
1517
}
1618

1719
namespace Test3 {
@@ -20,18 +22,23 @@ namespace Test3 {
2022
}
2123

2224
var x: Foo.bar = "";
25+
var y: Test3.Foo.bar = "";
2326
}
2427

2528
namespace Test4 {
2629
export type Foo = { bar: number }
2730
| { bar: string }
2831

2932
var x: Foo.bar = "";
33+
var y: Test4.Foo.bar = "";
3034
}
3135

3236
namespace Test5 {
3337
export type Foo = { bar: number }
3438
| { wat: string }
3539

3640
var x: Foo.bar = "";
37-
}
41+
var y: Test5.Foo.bar = "";
42+
}
43+
44+
import lol = Test5.Foo.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
4+
//// namespace Container {
5+
//// export interface Foo {
6+
//// bar: string;
7+
//// }
8+
//// }
9+
//// const x: [|Container.Foo.bar|] = ""
10+
11+
verify.not.codeFixAvailable();
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// export interface Foo {
4+
//// bar: string;
5+
//// }
6+
//// const x: [|Foo.bar|] = ""
7+
8+
verify.rangeAfterCodeFix(`Foo["bar"]`);

0 commit comments

Comments
 (0)