allow calling goToDef on modifiers of named declarations (#60384)

This commit is contained in:
Isabel Duan 2025-01-23 17:30:35 -08:00 committed by GitHub
parent f28c5180df
commit c5058f0066
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 1249 additions and 36 deletions

View File

@ -64,7 +64,9 @@ import {
isJSDocOverrideTag,
isJsxOpeningLikeElement,
isJumpStatementTarget,
isModifier,
isModuleSpecifierLike,
isNamedDeclaration,
isNameOfFunctionDeclaration,
isNewExpressionTarget,
isObjectBindingPattern,
@ -128,7 +130,10 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile
const typeChecker = program.getTypeChecker();
if (node.kind === SyntaxKind.OverrideKeyword || (isIdentifier(node) && isJSDocOverrideTag(parent) && parent.tagName === node)) {
return getDefinitionFromOverriddenMember(typeChecker, node) || emptyArray;
const def = getDefinitionFromOverriddenMember(typeChecker, node);
if (def !== undefined || node.kind !== SyntaxKind.OverrideKeyword) {
return def || emptyArray;
}
}
// Labels
@ -137,15 +142,8 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile
return label ? [createDefinitionInfoFromName(typeChecker, label, ScriptElementKind.label, node.text, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217
}
// for switch statments
switch (node.kind) {
case SyntaxKind.ReturnKeyword:
const functionDeclaration = findAncestor(node.parent, n =>
isClassStaticBlockDeclaration(n)
? "quit"
: isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined;
return functionDeclaration
? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)]
: undefined;
case SyntaxKind.DefaultKeyword:
if (!isDefaultClause(node.parent)) {
break;
@ -159,16 +157,15 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile
break;
}
if (node.kind === SyntaxKind.AwaitKeyword) {
const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n));
const isAsyncFunction = functionDeclaration && some(functionDeclaration.modifiers, node => node.kind === SyntaxKind.AsyncKeyword);
return isAsyncFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined;
}
if (node.kind === SyntaxKind.YieldKeyword) {
const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n));
const isGeneratorFunction = functionDeclaration && functionDeclaration.asteriskToken;
return isGeneratorFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined;
// for keywords related to function or method definitions
let findFunctionDecl: ((n: Node) => boolean | "quit") | undefined;
switch (node.kind) {
case SyntaxKind.ReturnKeyword:
case SyntaxKind.AwaitKeyword:
case SyntaxKind.YieldKeyword:
findFunctionDecl = isFunctionLikeDeclaration;
const functionDeclaration = findAncestor(node, findFunctionDecl) as FunctionLikeDeclaration | undefined;
return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined;
}
if (isStaticModifier(node) && isClassStaticBlockDeclaration(node.parent)) {
@ -217,6 +214,10 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile
}
}
if (isModifier(node) && (isClassElement(parent) || isNamedDeclaration(parent))) {
symbol = parent.symbol;
}
// Could not find a symbol e.g. node is string or number keyword,
// or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
if (!symbol) {
@ -457,7 +458,11 @@ export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile
if (isImportMeta(node.parent) && node.parent.name === node) {
return definitionFromType(typeChecker.getTypeAtLocation(node.parent), typeChecker, node.parent, /*failedAliasResolution*/ false);
}
const { symbol, failedAliasResolution } = getSymbol(node, typeChecker, /*stopAtAlias*/ false);
let { symbol, failedAliasResolution } = getSymbol(node, typeChecker, /*stopAtAlias*/ false);
if (isModifier(node) && (isClassElement(node.parent) || isNamedDeclaration(node.parent))) {
symbol = node.parent.symbol;
failedAliasResolution = false;
}
if (!symbol) return undefined;
const typeAtLocation = typeChecker.getTypeOfSymbolAtLocation(symbol, node);

View File

@ -26,6 +26,18 @@
// async function foo() {
// await Promise.resolve(0);
// }
// function notAsync() {
// <|function [|notAsync|]() {
// /*GOTO DEF*/await Promise.resolve(0);
// }
// }|>
// === Details ===
[
{
"kind": "function",
"name": "notAsync",
"containerName": "",
"isLocal": false,
"isAmbient": false,
"unverified": false
}
]

View File

@ -1,12 +1,26 @@
// === goToDefinition ===
// === /tests/cases/fourslash/goToDefinitionAwait3.ts ===
// class C {
// notAsync() {
// <|[|notAsync|]() {
// /*GOTO DEF*/await Promise.resolve(0);
// }
// }|>
//
// async foo() {
// --- (line: 7) skipped ---
// await Promise.resolve(0);
// }
// }
// === Details ===
[
{
"kind": "method",
"name": "notAsync",
"containerName": "C",
"isLocal": false,
"isAmbient": false,
"unverified": false
}
]

View File

@ -0,0 +1,18 @@
// === goToDefinition ===
// === /a.ts ===
// class A {
// <|private [|{| textSpan: true |}z|]/*GOTO DEF*/: string;|>
// }
// === Details ===
[
{
"kind": "property",
"name": "z",
"containerName": "A",
"isLocal": true,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]

View File

@ -0,0 +1,417 @@
// === goToDefinition ===
// === /a.ts ===
// /*GOTO DEF*/<|export class [|A|] {
//
// private z: string;
//
// readonly x: string;
//
// async a() { }
//
// override b() {}
//
// public async c() { }
// }|>
//
// export function foo() { }
// === Details ===
[
{
"kind": "class",
"name": "A",
"containerName": "\"/a\"",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// <|export class [|{| textSpan: true |}A|]/*GOTO DEF*/ {
//
// private z: string;
//
// readonly x: string;
//
// async a() { }
//
// override b() {}
//
// public async c() { }
// }|>
//
// export function foo() { }
// === Details ===
[
{
"kind": "class",
"name": "A",
"containerName": "\"/a\"",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// export class A {
//
// /*GOTO DEF*/<|private [|z|]: string;|>
//
// readonly x: string;
//
// --- (line: 7) skipped ---
// === Details ===
[
{
"kind": "property",
"name": "z",
"containerName": "A",
"isLocal": true,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// export class A {
//
// <|private [|{| textSpan: true |}z|]/*GOTO DEF*/: string;|>
//
// readonly x: string;
//
// --- (line: 7) skipped ---
// === Details ===
[
{
"kind": "property",
"name": "z",
"containerName": "A",
"isLocal": true,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// export class A {
//
// private z: string;
//
// /*GOTO DEF*/<|readonly [|x|]: string;|>
//
// async a() { }
//
// --- (line: 9) skipped ---
// === Details ===
[
{
"kind": "property",
"name": "x",
"containerName": "A",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// export class A {
//
// private z: string;
//
// <|readonly [|{| textSpan: true |}x|]/*GOTO DEF*/: string;|>
//
// async a() { }
//
// --- (line: 9) skipped ---
// === Details ===
[
{
"kind": "property",
"name": "x",
"containerName": "A",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// --- (line: 3) skipped ---
//
// readonly x: string;
//
// /*GOTO DEF*/<|async [|a|]() { }|>
//
// override b() {}
//
// --- (line: 11) skipped ---
// === Details ===
[
{
"kind": "method",
"name": "a",
"containerName": "A",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// --- (line: 3) skipped ---
//
// readonly x: string;
//
// <|async [|{| textSpan: true |}a|]/*GOTO DEF*/() { }|>
//
// override b() {}
//
// --- (line: 11) skipped ---
// === Details ===
[
{
"kind": "method",
"name": "a",
"containerName": "A",
"isLocal": false,
"isAmbient": false
}
]
// === goToDefinition ===
// === /a.ts ===
// --- (line: 5) skipped ---
//
// async a() { }
//
// /*GOTO DEF*/<|override [|b|]() {}|>
//
// public async c() { }
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "method",
"name": "b",
"containerName": "A",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// --- (line: 5) skipped ---
//
// async a() { }
//
// <|override [|{| textSpan: true |}b|]/*GOTO DEF*/() {}|>
//
// public async c() { }
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "method",
"name": "b",
"containerName": "A",
"isLocal": false,
"isAmbient": false
}
]
// === goToDefinition ===
// === /a.ts ===
// --- (line: 7) skipped ---
//
// override b() {}
//
// /*GOTO DEF*/<|public async [|c|]() { }|>
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "method",
"name": "c",
"containerName": "A",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// --- (line: 7) skipped ---
//
// override b() {}
//
// <|public/*GOTO DEF*/ async [|c|]() { }|>
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "method",
"name": "c",
"containerName": "A",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// --- (line: 7) skipped ---
//
// override b() {}
//
// <|public as/*GOTO DEF*/ync [|c|]() { }|>
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "method",
"name": "c",
"containerName": "A",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// --- (line: 7) skipped ---
//
// override b() {}
//
// <|public async [|{| textSpan: true |}c|]/*GOTO DEF*/() { }|>
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "method",
"name": "c",
"containerName": "A",
"isLocal": false,
"isAmbient": false
}
]
// === goToDefinition ===
// === /a.ts ===
// --- (line: 10) skipped ---
// public async c() { }
// }
//
// <|exp/*GOTO DEF*/ort function [|foo|]() { }|>
// === Details ===
[
{
"kind": "function",
"name": "foo",
"containerName": "\"/a\"",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToDefinition ===
// === /a.ts ===
// --- (line: 10) skipped ---
// public async c() { }
// }
//
// <|export function [|{| textSpan: true |}foo|]/*GOTO DEF*/() { }|>
// === Details ===
[
{
"kind": "function",
"name": "foo",
"containerName": "\"/a\"",
"isLocal": false,
"isAmbient": false
}
]

View File

@ -4,5 +4,18 @@
// m() {}
// }
// class Bar extends Foo {
// /*GOTO DEF*/override m1() {}
// }
// /*GOTO DEF*/<|override [|m1|]() {}|>
// }
// === Details ===
[
{
"kind": "method",
"name": "m1",
"containerName": "Bar",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]

View File

@ -1,5 +1,18 @@
// === goToDefinition ===
// === /tests/cases/fourslash/goToDefinitionOverriddenMember7.ts ===
// class Foo {
// /*GOTO DEF*/override m() {}
// }
// /*GOTO DEF*/<|override [|m|]() {}|>
// }
// === Details ===
[
{
"kind": "method",
"name": "m",
"containerName": "Foo",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]

View File

@ -1,7 +1,19 @@
// === goToDefinition ===
// === /tests/cases/fourslash/goToDefinitionReturn5.ts ===
// function foo() {
// <|function [|foo|]() {
// class Foo {
// static { /*GOTO DEF*/return; }
// }
// }
// }|>
// === Details ===
[
{
"kind": "function",
"name": "foo",
"containerName": "",
"isLocal": false,
"isAmbient": false,
"unverified": false
}
]

View File

@ -1,12 +1,26 @@
// === goToDefinition ===
// === /tests/cases/fourslash/goToDefinitionYield3.ts ===
// class C {
// notAGenerator() {
// <|[|notAGenerator|]() {
// /*GOTO DEF*/yield 0;
// }
// }|>
//
// foo*() {
// --- (line: 7) skipped ---
// yield 0;
// }
// }
// === Details ===
[
{
"kind": "method",
"name": "notAGenerator",
"containerName": "C",
"isLocal": false,
"isAmbient": false,
"unverified": false
}
]

View File

@ -1,5 +1,17 @@
// === goToDefinition ===
// === /tests/cases/fourslash/goToDefinitionYield4.ts ===
// function* gen() {
// class C { [/*GOTO DEF*/yield 10]() {} }
// }
// class C { <|[|[/*GOTO DEF*/yield 10]|]() {}|> }
// }
// === Details ===
[
{
"kind": "method",
"name": "[yield 10]",
"containerName": "C",
"isLocal": true,
"isAmbient": false,
"unverified": false
}
]

View File

@ -0,0 +1,597 @@
// === goToType ===
// === /a.ts ===
// /*GOTO TYPE*/<|export class [|A|] {
//
// private z: string;
//
// private y: A;
//
// readonly x: string;
//
// async a() { }
//
// override b() {}
//
// public async c() { }
// }|>
//
// export function foo() { }
// === Details ===
[
{
"kind": "class",
"name": "A",
"containerName": "\"/a\"",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === /a.ts ===
// <|export class [|A|]/*GOTO TYPE*/ {
//
// private z: string;
//
// private y: A;
//
// readonly x: string;
//
// async a() { }
//
// override b() {}
//
// public async c() { }
// }|>
//
// export function foo() { }
// === Details ===
[
{
"kind": "class",
"name": "A",
"containerName": "\"/a\"",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === /a.ts ===
// export class A {
//
// /*GOTO TYPE*/private z: string;
//
// private y: A;
//
// --- (line: 7) skipped ---
// === goToType ===
// === /a.ts ===
// export class A {
//
// private z/*GOTO TYPE*/: string;
//
// private y: A;
//
// --- (line: 7) skipped ---
// === goToType ===
// === /a.ts ===
// <|export class [|A|] {
//
// private z: string;
//
// /*GOTO TYPE*/private y: A;
//
// readonly x: string;
//
// async a() { }
//
// override b() {}
//
// public async c() { }
// }|>
//
// export function foo() { }
// === Details ===
[
{
"kind": "class",
"name": "A",
"containerName": "\"/a\"",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === /a.ts ===
// <|export class [|A|] {
//
// private z: string;
//
// private y/*GOTO TYPE*/: A;
//
// readonly x: string;
//
// async a() { }
//
// override b() {}
//
// public async c() { }
// }|>
//
// export function foo() { }
// === Details ===
[
{
"kind": "class",
"name": "A",
"containerName": "\"/a\"",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === /a.ts ===
// --- (line: 3) skipped ---
//
// private y: A;
//
// /*GOTO TYPE*/readonly x: string;
//
// async a() { }
//
// --- (line: 11) skipped ---
// === goToType ===
// === /a.ts ===
// --- (line: 3) skipped ---
//
// private y: A;
//
// readonly x/*GOTO TYPE*/: string;
//
// async a() { }
//
// --- (line: 11) skipped ---
// === goToType ===
// === lib.d.ts ===
// --- (line: --) skipped ---
// /**
// * Represents the completion of an asynchronous operation
// */
// <|interface [|Promise|]<T> {
// /**
// * Attaches callbacks for the resolution and/or rejection of the Promise.
// * @param onfulfilled The callback to execute when the Promise is resolved.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of which ever callback is executed.
// */
// then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
//
// /**
// * Attaches a callback for only the rejection of the Promise.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of the callback.
// */
// catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
// }|>
//
// /**
// * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
// --- (line: --) skipped ---
// === /a.ts ===
// --- (line: 5) skipped ---
//
// readonly x: string;
//
// /*GOTO TYPE*/async a() { }
//
// override b() {}
//
// --- (line: 13) skipped ---
// === Details ===
[
{
"kind": "interface",
"name": "Promise",
"containerName": "",
"isLocal": false,
"isAmbient": true,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === lib.d.ts ===
// --- (line: --) skipped ---
// /**
// * Represents the completion of an asynchronous operation
// */
// <|interface [|Promise|]<T> {
// /**
// * Attaches callbacks for the resolution and/or rejection of the Promise.
// * @param onfulfilled The callback to execute when the Promise is resolved.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of which ever callback is executed.
// */
// then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
//
// /**
// * Attaches a callback for only the rejection of the Promise.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of the callback.
// */
// catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
// }|>
//
// /**
// * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
// --- (line: --) skipped ---
// === /a.ts ===
// --- (line: 5) skipped ---
//
// readonly x: string;
//
// async a/*GOTO TYPE*/() { }
//
// override b() {}
//
// --- (line: 13) skipped ---
// === Details ===
[
{
"kind": "interface",
"name": "Promise",
"containerName": "",
"isLocal": false,
"isAmbient": true,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === /a.ts ===
// --- (line: 7) skipped ---
//
// async a() { }
//
// /*GOTO TYPE*/<|override [|b|]() {}|>
//
// public async c() { }
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "method",
"name": "b",
"containerName": "A",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === /a.ts ===
// --- (line: 7) skipped ---
//
// async a() { }
//
// <|override [|b|]/*GOTO TYPE*/() {}|>
//
// public async c() { }
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "method",
"name": "b",
"containerName": "A",
"isLocal": false,
"isAmbient": false
}
]
// === goToType ===
// === lib.d.ts ===
// --- (line: --) skipped ---
// /**
// * Represents the completion of an asynchronous operation
// */
// <|interface [|Promise|]<T> {
// /**
// * Attaches callbacks for the resolution and/or rejection of the Promise.
// * @param onfulfilled The callback to execute when the Promise is resolved.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of which ever callback is executed.
// */
// then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
//
// /**
// * Attaches a callback for only the rejection of the Promise.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of the callback.
// */
// catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
// }|>
//
// /**
// * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
// --- (line: --) skipped ---
// === /a.ts ===
// --- (line: 9) skipped ---
//
// override b() {}
//
// /*GOTO TYPE*/public async c() { }
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "interface",
"name": "Promise",
"containerName": "",
"isLocal": false,
"isAmbient": true,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === lib.d.ts ===
// --- (line: --) skipped ---
// /**
// * Represents the completion of an asynchronous operation
// */
// <|interface [|Promise|]<T> {
// /**
// * Attaches callbacks for the resolution and/or rejection of the Promise.
// * @param onfulfilled The callback to execute when the Promise is resolved.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of which ever callback is executed.
// */
// then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
//
// /**
// * Attaches a callback for only the rejection of the Promise.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of the callback.
// */
// catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
// }|>
//
// /**
// * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
// --- (line: --) skipped ---
// === /a.ts ===
// --- (line: 9) skipped ---
//
// override b() {}
//
// public/*GOTO TYPE*/ async c() { }
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "interface",
"name": "Promise",
"containerName": "",
"isLocal": false,
"isAmbient": true,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === lib.d.ts ===
// --- (line: --) skipped ---
// /**
// * Represents the completion of an asynchronous operation
// */
// <|interface [|Promise|]<T> {
// /**
// * Attaches callbacks for the resolution and/or rejection of the Promise.
// * @param onfulfilled The callback to execute when the Promise is resolved.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of which ever callback is executed.
// */
// then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
//
// /**
// * Attaches a callback for only the rejection of the Promise.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of the callback.
// */
// catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
// }|>
//
// /**
// * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
// --- (line: --) skipped ---
// === /a.ts ===
// --- (line: 9) skipped ---
//
// override b() {}
//
// public as/*GOTO TYPE*/ync c() { }
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "interface",
"name": "Promise",
"containerName": "",
"isLocal": false,
"isAmbient": true,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === lib.d.ts ===
// --- (line: --) skipped ---
// /**
// * Represents the completion of an asynchronous operation
// */
// <|interface [|Promise|]<T> {
// /**
// * Attaches callbacks for the resolution and/or rejection of the Promise.
// * @param onfulfilled The callback to execute when the Promise is resolved.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of which ever callback is executed.
// */
// then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
//
// /**
// * Attaches a callback for only the rejection of the Promise.
// * @param onrejected The callback to execute when the Promise is rejected.
// * @returns A Promise for the completion of the callback.
// */
// catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
// }|>
//
// /**
// * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
// --- (line: --) skipped ---
// === /a.ts ===
// --- (line: 9) skipped ---
//
// override b() {}
//
// public async c/*GOTO TYPE*/() { }
// }
//
// export function foo() { }
// === Details ===
[
{
"kind": "interface",
"name": "Promise",
"containerName": "",
"isLocal": false,
"isAmbient": true,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === /a.ts ===
// --- (line: 12) skipped ---
// public async c() { }
// }
//
// <|exp/*GOTO TYPE*/ort function [|foo|]() { }|>
// === Details ===
[
{
"kind": "function",
"name": "foo",
"containerName": "\"/a\"",
"isLocal": false,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]
// === goToType ===
// === /a.ts ===
// --- (line: 12) skipped ---
// public async c() { }
// }
//
// <|export function [|foo|]/*GOTO TYPE*/() { }|>
// === Details ===
[
{
"kind": "function",
"name": "foo",
"containerName": "\"/a\"",
"isLocal": false,
"isAmbient": false
}
]

View File

@ -0,0 +1,10 @@
/// <reference path='fourslash.ts'/>
// @Filename: /a.ts
//// class A {
//// private z/*z*/: string;
//// }
verify.baselineGoToDefinition(
"z"
);

View File

@ -0,0 +1,36 @@
/// <reference path='fourslash.ts'/>
// @Filename: /a.ts
//// /*export*/export class A/*A*/ {
////
//// /*private*/private z/*z*/: string;
////
//// /*readonly*/readonly x/*x*/: string;
////
//// /*async*/async a/*a*/() { }
////
//// /*override*/override b/*b*/() {}
////
//// /*public1*/public/*public2*/ as/*multipleModifiers*/ync c/*c*/() { }
//// }
////
//// exp/*exportFunction*/ort function foo/*foo*/() { }
verify.baselineGoToDefinition(
"export",
"A",
"private",
"z",
"readonly",
"x",
"async",
"a",
"override",
"b",
"public1",
"public2",
"multipleModifiers",
"c",
"exportFunction",
"foo"
);

View File

@ -0,0 +1,40 @@
/// <reference path='fourslash.ts'/>
// @Filename: /a.ts
//// /*export*/export class A/*A*/ {
////
//// /*private*/private z/*z*/: string;
////
//// /*private2*/private y/*y*/: A;
////
//// /*readonly*/readonly x/*x*/: string;
////
//// /*async*/async a/*a*/() { }
////
//// /*override*/override b/*b*/() {}
////
//// /*public1*/public/*public2*/ as/*multipleModifiers*/ync c/*c*/() { }
//// }
////
//// exp/*exportFunction*/ort function foo/*foo*/() { }
verify.baselineGoToType(
"export",
"A",
"private",
"z",
"private2",
"y",
"readonly",
"x",
"async",
"a",
"override",
"b",
"public1",
"public2",
"multipleModifiers",
"c",
"exportFunction",
"foo"
);