support quickinfo and go-to-definition on typeof this (#47085)

* support quickinfo and go-to-definition on `typeof this`

* update baseline

* move code to checkIdentifier
This commit is contained in:
Zzzen
2022-02-01 16:16:01 -08:00
committed by GitHub
parent 7cc0f755ce
commit 880e2c0783
11 changed files with 536 additions and 25 deletions
+8 -1
View File
@@ -25107,6 +25107,10 @@ namespace ts {
}
function checkIdentifier(node: Identifier, checkMode: CheckMode | undefined): Type {
if (isThisInTypeQuery(node)) {
return checkThisExpression(node);
}
const symbol = getResolvedSymbol(node);
if (symbol === unknownSymbol) {
return errorType;
@@ -41245,7 +41249,10 @@ namespace ts {
case SyntaxKind.PrivateIdentifier:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.QualifiedName:
return getSymbolOfNameOrPropertyAccessExpression(node as EntityName | PrivateIdentifier | PropertyAccessExpression);
if (!isThisInTypeQuery(node)) {
return getSymbolOfNameOrPropertyAccessExpression(node as EntityName | PrivateIdentifier | PropertyAccessExpression);
}
// falls through
case SyntaxKind.ThisKeyword:
const container = getThisContainer(node, /*includeArrowFunctions*/ false);
+2 -2
View File
@@ -41,7 +41,7 @@ namespace ts.SymbolDisplay {
if (typeChecker.isArgumentsSymbol(symbol)) {
return ScriptElementKind.localVariableElement;
}
if (location.kind === SyntaxKind.ThisKeyword && isExpression(location)) {
if (location.kind === SyntaxKind.ThisKeyword && isExpression(location) || isThisInTypeQuery(location)) {
return ScriptElementKind.parameterElement;
}
const flags = getCombinedLocalAndExportSymbolFlags(symbol);
@@ -143,7 +143,7 @@ namespace ts.SymbolDisplay {
const symbolFlags = getCombinedLocalAndExportSymbolFlags(symbol);
let symbolKind = semanticMeaning & SemanticMeaning.Value ? getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) : ScriptElementKind.unknown;
let hasAddedSymbolInfo = false;
const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isInExpressionContext(location);
const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isInExpressionContext(location) || isThisInTypeQuery(location);
let type: Type | undefined;
let printer: Printer;
let documentationFromAlias: SymbolDisplayPart[] | undefined;
@@ -16,6 +16,7 @@ class C {
d: typeof this.z; // error
>d : Symbol(C.d, Decl(initializerReferencingConstructorLocals.ts, 5, 15))
>this : Symbol(C, Decl(initializerReferencingConstructorLocals.ts, 0, 0))
constructor(x) {
>x : Symbol(x, Decl(initializerReferencingConstructorLocals.ts, 7, 16))
@@ -40,6 +41,7 @@ class D<T> {
d: typeof this.z; // error
>d : Symbol(D.d, Decl(initializerReferencingConstructorLocals.ts, 15, 15))
>this : Symbol(D, Decl(initializerReferencingConstructorLocals.ts, 10, 1))
constructor(x: T) {
>x : Symbol(x, Decl(initializerReferencingConstructorLocals.ts, 17, 16))
@@ -21,7 +21,7 @@ class C {
d: typeof this.z; // error
>d : any
>this.z : any
>this : any
>this : this
>z : any
constructor(x) {
@@ -54,7 +54,7 @@ class D<T> {
d: typeof this.z; // error
>d : any
>this.z : any
>this : any
>this : this
>z : any
constructor(x: T) {
@@ -39,6 +39,7 @@ class E {
b: typeof this.x; // ok
>b : Symbol(E.b, Decl(initializerReferencingConstructorParameters.ts, 15, 15))
>this.x : Symbol(E.x, Decl(initializerReferencingConstructorParameters.ts, 17, 16))
>this : Symbol(E, Decl(initializerReferencingConstructorParameters.ts, 12, 1))
>x : Symbol(E.x, Decl(initializerReferencingConstructorParameters.ts, 17, 16))
constructor(public x) { }
@@ -43,7 +43,7 @@ class E {
b: typeof this.x; // ok
>b : any
>this.x : any
>this : any
>this : this
>x : any
constructor(public x) { }
@@ -0,0 +1,443 @@
[
{
"marker": {
"fileName": "/tests/cases/fourslash/quickInfoOnThis5.ts",
"position": 62,
"name": "1"
},
"quickInfo": {
"kind": "",
"kindModifiers": "",
"textSpan": {
"start": 60,
"length": 4
},
"displayParts": [
{
"text": "{",
"kind": "punctuation"
},
{
"text": "\n",
"kind": "lineBreak"
},
{
"text": " ",
"kind": "space"
},
{
"text": "num",
"kind": "propertyName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "number",
"kind": "keyword"
},
{
"text": ";",
"kind": "punctuation"
},
{
"text": "\n",
"kind": "lineBreak"
},
{
"text": " ",
"kind": "space"
},
{
"text": "f",
"kind": "text"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "void",
"kind": "keyword"
},
{
"text": ";",
"kind": "punctuation"
},
{
"text": "\n",
"kind": "lineBreak"
},
{
"text": " ",
"kind": "space"
},
{
"text": "g",
"kind": "text"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": "this",
"kind": "parameterName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "number",
"kind": "keyword"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "void",
"kind": "keyword"
},
{
"text": ";",
"kind": "punctuation"
},
{
"text": "\n",
"kind": "lineBreak"
},
{
"text": "}",
"kind": "punctuation"
}
],
"documentation": [],
"tags": []
}
},
{
"marker": {
"fileName": "/tests/cases/fourslash/quickInfoOnThis5.ts",
"position": 92,
"name": "2"
},
"quickInfo": {
"kind": "parameter",
"kindModifiers": "",
"textSpan": {
"start": 90,
"length": 4
},
"displayParts": [
{
"text": "this",
"kind": "keyword"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "{",
"kind": "punctuation"
},
{
"text": "\n",
"kind": "lineBreak"
},
{
"text": " ",
"kind": "space"
},
{
"text": "num",
"kind": "propertyName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "number",
"kind": "keyword"
},
{
"text": ";",
"kind": "punctuation"
},
{
"text": "\n",
"kind": "lineBreak"
},
{
"text": " ",
"kind": "space"
},
{
"text": "f",
"kind": "text"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "void",
"kind": "keyword"
},
{
"text": ";",
"kind": "punctuation"
},
{
"text": "\n",
"kind": "lineBreak"
},
{
"text": " ",
"kind": "space"
},
{
"text": "g",
"kind": "text"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": "this",
"kind": "parameterName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "number",
"kind": "keyword"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "void",
"kind": "keyword"
},
{
"text": ";",
"kind": "punctuation"
},
{
"text": "\n",
"kind": "lineBreak"
},
{
"text": "}",
"kind": "punctuation"
}
],
"documentation": []
}
},
{
"marker": {
"fileName": "/tests/cases/fourslash/quickInfoOnThis5.ts",
"position": 155,
"name": "3"
},
"quickInfo": {
"kind": "parameter",
"kindModifiers": "",
"textSpan": {
"start": 153,
"length": 4
},
"displayParts": [
{
"text": "this",
"kind": "keyword"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "number",
"kind": "keyword"
}
],
"documentation": []
}
},
{
"marker": {
"fileName": "/tests/cases/fourslash/quickInfoOnThis5.ts",
"position": 228,
"name": "4"
},
"quickInfo": {
"kind": "parameter",
"kindModifiers": "",
"textSpan": {
"start": 226,
"length": 4
},
"displayParts": [
{
"text": "this",
"kind": "keyword"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "this",
"kind": "keyword"
}
],
"documentation": []
}
},
{
"marker": {
"fileName": "/tests/cases/fourslash/quickInfoOnThis5.ts",
"position": 258,
"name": "5"
},
"quickInfo": {
"kind": "parameter",
"kindModifiers": "",
"textSpan": {
"start": 256,
"length": 4
},
"displayParts": [
{
"text": "this",
"kind": "keyword"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "this",
"kind": "keyword"
}
],
"documentation": []
}
},
{
"marker": {
"fileName": "/tests/cases/fourslash/quickInfoOnThis5.ts",
"position": 320,
"name": "6"
},
"quickInfo": {
"kind": "parameter",
"kindModifiers": "",
"textSpan": {
"start": 318,
"length": 4
},
"displayParts": [
{
"text": "this",
"kind": "keyword"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "number",
"kind": "keyword"
}
],
"documentation": []
}
}
]
@@ -9,6 +9,7 @@ class Test {
var copy: typeof this.data = {};
>copy : Symbol(copy, Decl(typeofThis.ts, 3, 11))
>this.data : Symbol(Test.data, Decl(typeofThis.ts, 0, 12))
>this : Symbol(Test, Decl(typeofThis.ts, 0, 0))
>data : Symbol(Test.data, Decl(typeofThis.ts, 0, 12))
}
}
@@ -28,6 +29,7 @@ class Test1 {
var copy: typeof this.data = { foo: '' };
>copy : Symbol(copy, Decl(typeofThis.ts, 11, 11))
>this.data : Symbol(Test1.data, Decl(typeofThis.ts, 7, 13))
>this : Symbol(Test1, Decl(typeofThis.ts, 5, 1))
>data : Symbol(Test1.data, Decl(typeofThis.ts, 7, 13))
>foo : Symbol(foo, Decl(typeofThis.ts, 11, 38))
@@ -35,11 +37,13 @@ class Test1 {
>foo : Symbol(foo, Decl(typeofThis.ts, 12, 11))
>this.data.foo : Symbol(foo, Decl(typeofThis.ts, 8, 12))
>this.data : Symbol(Test1.data, Decl(typeofThis.ts, 7, 13))
>this : Symbol(Test1, Decl(typeofThis.ts, 5, 1))
>data : Symbol(Test1.data, Decl(typeofThis.ts, 7, 13))
>foo : Symbol(foo, Decl(typeofThis.ts, 8, 12))
var self: typeof this = this;
>self : Symbol(self, Decl(typeofThis.ts, 14, 11))
>this : Symbol(Test1, Decl(typeofThis.ts, 5, 1))
>this : Symbol(Test1, Decl(typeofThis.ts, 5, 1))
self.data;
@@ -50,6 +54,7 @@ class Test1 {
var str: typeof this.this = '';
>str : Symbol(str, Decl(typeofThis.ts, 17, 11))
>this.this : Symbol(Test1['this'], Decl(typeofThis.ts, 8, 23))
>this : Symbol(Test1, Decl(typeofThis.ts, 5, 1))
>this : Symbol(Test1['this'], Decl(typeofThis.ts, 8, 23))
}
}
@@ -99,6 +104,7 @@ class Test5 {
let x: typeof this.no = 1;
>x : Symbol(x, Decl(typeofThis.ts, 39, 11))
>this.no : Symbol(Test5.no, Decl(typeofThis.ts, 34, 13))
>this : Symbol(Test5, Decl(typeofThis.ts, 32, 1))
>no : Symbol(Test5.no, Decl(typeofThis.ts, 34, 13))
}
}
@@ -130,6 +136,7 @@ const Test8 = () => {
let x: typeof this.no = 1;
>x : Symbol(x, Decl(typeofThis.ts, 56, 7))
>this : Symbol(globalThis)
}
class Test9 {
@@ -150,6 +157,7 @@ class Test9 {
const d1: typeof this = this;
>d1 : Symbol(d1, Decl(typeofThis.ts, 65, 17))
>this : Symbol(Test9, Decl(typeofThis.ts, 57, 1))
d1.f1();
>d1.f1 : Symbol(Test9D1.f1, Decl(typeofThis.ts, 86, 15))
@@ -163,6 +171,7 @@ class Test9 {
const d2: typeof this = this;
>d2 : Symbol(d2, Decl(typeofThis.ts, 70, 17))
>this : Symbol(Test9, Decl(typeofThis.ts, 57, 1))
d2.f2();
>d2.f2 : Symbol(Test9D2.f2, Decl(typeofThis.ts, 90, 15))
@@ -182,6 +191,7 @@ class Test9 {
const no: typeof this.no = this.no;
>no : Symbol(no, Decl(typeofThis.ts, 77, 17))
>this.no : Symbol(Test9.no, Decl(typeofThis.ts, 59, 13))
>this : Symbol(Test9, Decl(typeofThis.ts, 57, 1))
>no : Symbol(Test9.no, Decl(typeofThis.ts, 59, 13))
>this.no : Symbol(Test9.no, Decl(typeofThis.ts, 59, 13))
>this : Symbol(Test9, Decl(typeofThis.ts, 57, 1))
@@ -196,6 +206,7 @@ class Test9 {
const no: typeof this.this = this.this;
>no : Symbol(no, Decl(typeofThis.ts, 81, 17))
>this.this : Symbol(Test9.this, Decl(typeofThis.ts, 60, 11))
>this : Symbol(Test9, Decl(typeofThis.ts, 57, 1))
>this : Symbol(Test9.this, Decl(typeofThis.ts, 60, 11))
>this.this : Symbol(Test9.this, Decl(typeofThis.ts, 60, 11))
>this : Symbol(Test9, Decl(typeofThis.ts, 57, 1))
@@ -231,6 +242,7 @@ class Test10 {
let a: typeof this.a = undefined as any;
>a : Symbol(a, Decl(typeofThis.ts, 98, 11))
>this.a : Symbol(Test10.a, Decl(typeofThis.ts, 94, 14))
>this : Symbol(Test10, Decl(typeofThis.ts, 92, 1))
>a : Symbol(Test10.a, Decl(typeofThis.ts, 94, 14))
>undefined : Symbol(undefined)
@@ -242,6 +254,7 @@ class Test10 {
let a: typeof this.a = undefined as any; // should narrow to { b?: string }
>a : Symbol(a, Decl(typeofThis.ts, 100, 15))
>this.a : Symbol(Test10.a, Decl(typeofThis.ts, 94, 14))
>this : Symbol(Test10, Decl(typeofThis.ts, 92, 1))
>a : Symbol(Test10.a, Decl(typeofThis.ts, 94, 14))
>undefined : Symbol(undefined)
@@ -249,6 +262,7 @@ class Test10 {
>b : Symbol(b, Decl(typeofThis.ts, 101, 15))
>this.a.b : Symbol(b, Decl(typeofThis.ts, 95, 9))
>this.a : Symbol(Test10.a, Decl(typeofThis.ts, 94, 14))
>this : Symbol(Test10, Decl(typeofThis.ts, 92, 1))
>a : Symbol(Test10.a, Decl(typeofThis.ts, 94, 14))
>b : Symbol(b, Decl(typeofThis.ts, 95, 9))
>undefined : Symbol(undefined)
@@ -264,6 +278,7 @@ class Test10 {
>b : Symbol(b, Decl(typeofThis.ts, 104, 19))
>this.a.b : Symbol(b, Decl(typeofThis.ts, 95, 9))
>this.a : Symbol(Test10.a, Decl(typeofThis.ts, 94, 14))
>this : Symbol(Test10, Decl(typeofThis.ts, 92, 1))
>a : Symbol(Test10.a, Decl(typeofThis.ts, 94, 14))
>b : Symbol(b, Decl(typeofThis.ts, 95, 9))
>undefined : Symbol(undefined)
@@ -321,6 +336,7 @@ class Tests12 {
type Test = typeof this;
>Test : Symbol(Test, Decl(typeofThis.ts, 124, 13))
>this : Symbol(Tests12, Decl(typeofThis.ts, 121, 1))
}
test2() { // OK
@@ -329,6 +345,7 @@ class Tests12 {
for (;;) {}
type Test = typeof this;
>Test : Symbol(Test, Decl(typeofThis.ts, 129, 19))
>this : Symbol(Tests12, Decl(typeofThis.ts, 121, 1))
}
test3() { // expected no compile errors
@@ -339,6 +356,7 @@ class Tests12 {
type Test = typeof this;
>Test : Symbol(Test, Decl(typeofThis.ts, 134, 34))
>this : Symbol(Tests12, Decl(typeofThis.ts, 121, 1))
}
test4() { // expected no compile errors
@@ -349,5 +367,6 @@ class Tests12 {
type Test = typeof this;
>Test : Symbol(Test, Decl(typeofThis.ts, 139, 34))
>this : Symbol(Tests12, Decl(typeofThis.ts, 121, 1))
}
}
+19 -19
View File
@@ -10,7 +10,7 @@ class Test {
var copy: typeof this.data = {};
>copy : {}
>this.data : {}
>this : any
>this : this
>data : {}
>{} : {}
}
@@ -34,7 +34,7 @@ class Test1 {
var copy: typeof this.data = { foo: '' };
>copy : { foo: string; }
>this.data : { foo: string; }
>this : any
>this : this
>data : { foo: string; }
>{ foo: '' } : { foo: string; }
>foo : string
@@ -44,14 +44,14 @@ class Test1 {
>foo : string
>this.data.foo : string
>this.data : { foo: string; }
>this : any
>this : this
>data : { foo: string; }
>foo : string
>'' : ""
var self: typeof this = this;
>self : this
>this : any
>this : this
>this : this
self.data;
@@ -62,7 +62,7 @@ class Test1 {
var str: typeof this.this = '';
>str : string
>this.this : string
>this : any
>this : this
>this : string
>'' : ""
}
@@ -121,7 +121,7 @@ class Test5 {
let x: typeof this.no = 1;
>x : number
>this.no : number
>this : any
>this : this
>no : number
>1 : 1
}
@@ -166,7 +166,7 @@ const Test8 = () => {
let x: typeof this.no = 1;
>x : any
>this.no : any
>this : any
>this : typeof globalThis
>no : any
>1 : 1
}
@@ -192,7 +192,7 @@ class Test9 {
const d1: typeof this = this;
>d1 : this & Test9D1
>this : any
>this : this & Test9D1
>this : this & Test9D1
d1.f1();
@@ -209,7 +209,7 @@ class Test9 {
const d2: typeof this = this;
>d2 : this & Test9D2
>this : any
>this : this & Test9D2
>this : this & Test9D2
d2.f2();
@@ -233,7 +233,7 @@ class Test9 {
const no: typeof this.no = this.no;
>no : 1
>this.no : 1
>this : any
>this : this
>no : 1
>this.no : 1
>this : this
@@ -250,7 +250,7 @@ class Test9 {
const no: typeof this.this = this.this;
>no : 1
>this.this : 1
>this : any
>this : this
>this : 1
>this.this : 1
>this : this
@@ -286,7 +286,7 @@ class Test10 {
let a: typeof this.a = undefined as any;
>a : { b?: string | undefined; } | undefined
>this.a : { b?: string | undefined; } | undefined
>this : any
>this : this
>a : { b?: string | undefined; } | undefined
>undefined as any : any
>undefined : undefined
@@ -299,7 +299,7 @@ class Test10 {
let a: typeof this.a = undefined as any; // should narrow to { b?: string }
>a : { b?: string | undefined; }
>this.a : { b?: string | undefined; }
>this : any
>this : this
>a : { b?: string | undefined; }
>undefined as any : any
>undefined : undefined
@@ -308,7 +308,7 @@ class Test10 {
>b : string | undefined
>this.a.b : string | undefined
>this.a : { b?: string | undefined; }
>this : any
>this : this
>a : { b?: string | undefined; }
>b : string | undefined
>undefined as any : any
@@ -325,7 +325,7 @@ class Test10 {
>b : string
>this.a.b : string
>this.a : { b?: string | undefined; }
>this : any
>this : this
>a : { b?: string | undefined; }
>b : string
>undefined as any : any
@@ -386,7 +386,7 @@ class Tests12 {
type Test = typeof this;
>Test : this
>this : any
>this : this
}
test2() { // OK
@@ -395,7 +395,7 @@ class Tests12 {
for (;;) {}
type Test = typeof this;
>Test : this
>this : any
>this : this
}
test3() { // expected no compile errors
@@ -407,7 +407,7 @@ class Tests12 {
type Test = typeof this;
>Test : this
>this : any
>this : this
}
test4() { // expected no compile errors
@@ -419,6 +419,6 @@ class Tests12 {
type Test = typeof this;
>Test : this
>this : any
>this : this
}
}
@@ -0,0 +1,15 @@
/// <reference path='fourslash.ts'/>
////function f(/*fnDecl*/this: number) {
//// type X = typeof [|/*fnUse*/this|];
////}
////class /*cls*/C {
//// constructor() { type X = typeof [|/*clsUse*/this|]; }
//// get self(/*getterDecl*/this: number) { type X = typeof [|/*getterUse*/this|]; }
////}
verify.goToDefinition({
"fnUse": "fnDecl",
"clsUse": "cls",
"getterUse": "getterDecl"
});
+24
View File
@@ -0,0 +1,24 @@
/// <reference path='fourslash.ts' />
// @noImplicitThis: true
////const foo = {
//// num: 0,
//// f() {
//// type Y = typeof th/*1*/is;
//// type Z = typeof th/*2*/is.num;
//// },
//// g(this: number) {
//// type X = typeof th/*3*/is;
//// }
////}
////class Foo {
//// num = 0;
//// f() {
//// type Y = typeof th/*4*/is;
//// type Z = typeof th/*5*/is.num;
//// }
//// g(this: number) {
//// type X = typeof th/*6*/is;
//// }
////}
verify.baselineQuickInfo();