diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 9a47d90ce1deb..083c5e4d53e7c 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -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,30 @@ 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; + // for keywords related to function or method definitions + let findFunctionDecl: ((n: Node) => boolean | "quit") | undefined; + let checkFunctionDeclaration: ((decl: FunctionLikeDeclaration) => boolean) | undefined; + switch (node.kind) { + case SyntaxKind.ReturnKeyword: + findFunctionDecl = n => { + return isClassStaticBlockDeclaration(n) + ? "quit" + : isFunctionLikeDeclaration(n); + }; + break; + case SyntaxKind.AwaitKeyword: + checkFunctionDeclaration = (functionDeclaration: FunctionLikeDeclaration) => some(functionDeclaration.modifiers, node => node.kind === SyntaxKind.AsyncKeyword); + findFunctionDecl = isFunctionLikeDeclaration; + break; + case SyntaxKind.YieldKeyword: + checkFunctionDeclaration = functionDeclaration => !!functionDeclaration.asteriskToken; + findFunctionDecl = isFunctionLikeDeclaration; + break; } - - if (node.kind === SyntaxKind.YieldKeyword) { - const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n)); - const isGeneratorFunction = functionDeclaration && functionDeclaration.asteriskToken; - return isGeneratorFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined; + if (findFunctionDecl) { + const functionDeclaration = findAncestor(node, findFunctionDecl) as FunctionLikeDeclaration | undefined; + const isCorrectDeclaration = functionDeclaration && (!checkFunctionDeclaration || checkFunctionDeclaration(functionDeclaration)); + return isCorrectDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined; } if (isStaticModifier(node) && isClassStaticBlockDeclaration(node.parent)) { @@ -217,6 +229,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 +473,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); diff --git a/tests/baselines/reference/goToDefinitionMember.baseline.jsonc b/tests/baselines/reference/goToDefinitionMember.baseline.jsonc new file mode 100644 index 0000000000000..56d045363ee91 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionMember.baseline.jsonc @@ -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 + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionModifiers.baseline.jsonc b/tests/baselines/reference/goToDefinitionModifiers.baseline.jsonc new file mode 100644 index 0000000000000..2916c40cfcf04 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionModifiers.baseline.jsonc @@ -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 + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember6.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember6.baseline.jsonc index 62684d5287adc..81f192334a6b4 100644 --- a/tests/baselines/reference/goToDefinitionOverriddenMember6.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionOverriddenMember6.baseline.jsonc @@ -4,5 +4,18 @@ // m() {} // } // class Bar extends Foo { -// /*GOTO DEF*/override m1() {} -// } \ No newline at end of file +// /*GOTO DEF*/<|override [|m1|]() {}|> +// } + + // === Details === + [ + { + "kind": "method", + "name": "m1", + "containerName": "Bar", + "isLocal": false, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember7.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember7.baseline.jsonc index 1b8e13a8715b2..95dc0b73f0459 100644 --- a/tests/baselines/reference/goToDefinitionOverriddenMember7.baseline.jsonc +++ b/tests/baselines/reference/goToDefinitionOverriddenMember7.baseline.jsonc @@ -1,5 +1,18 @@ // === goToDefinition === // === /tests/cases/fourslash/goToDefinitionOverriddenMember7.ts === // class Foo { -// /*GOTO DEF*/override m() {} -// } \ No newline at end of file +// /*GOTO DEF*/<|override [|m|]() {}|> +// } + + // === Details === + [ + { + "kind": "method", + "name": "m", + "containerName": "Foo", + "isLocal": false, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToTypeDefinitionModifiers.baseline.jsonc b/tests/baselines/reference/goToTypeDefinitionModifiers.baseline.jsonc new file mode 100644 index 0000000000000..0971205dbcaaf --- /dev/null +++ b/tests/baselines/reference/goToTypeDefinitionModifiers.baseline.jsonc @@ -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|] { +// /** +// * 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(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; +// +// /** +// * 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(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; +// }|> +// +// /** +// * 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|] { +// /** +// * 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(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; +// +// /** +// * 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(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; +// }|> +// +// /** +// * 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|] { +// /** +// * 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(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; +// +// /** +// * 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(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; +// }|> +// +// /** +// * 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|] { +// /** +// * 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(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; +// +// /** +// * 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(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; +// }|> +// +// /** +// * 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|] { +// /** +// * 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(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; +// +// /** +// * 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(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; +// }|> +// +// /** +// * 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|] { +// /** +// * 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(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; +// +// /** +// * 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(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; +// }|> +// +// /** +// * 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 + } + ] \ No newline at end of file diff --git a/tests/cases/fourslash/goToDefinitionMember.ts b/tests/cases/fourslash/goToDefinitionMember.ts new file mode 100644 index 0000000000000..c21e2799f5d8b --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionMember.ts @@ -0,0 +1,10 @@ +/// + +// @Filename: /a.ts +//// class A { +//// private z/*z*/: string; +//// } + +verify.baselineGoToDefinition( + "z" +); diff --git a/tests/cases/fourslash/goToDefinitionModifiers.ts b/tests/cases/fourslash/goToDefinitionModifiers.ts new file mode 100644 index 0000000000000..224b4e5677603 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionModifiers.ts @@ -0,0 +1,36 @@ +/// + +// @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" +); diff --git a/tests/cases/fourslash/goToTypeDefinitionModifiers.ts b/tests/cases/fourslash/goToTypeDefinitionModifiers.ts new file mode 100644 index 0000000000000..25b79734fa40f --- /dev/null +++ b/tests/cases/fourslash/goToTypeDefinitionModifiers.ts @@ -0,0 +1,40 @@ +/// + +// @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" +);