From 7558de69b1b73fc9383754839014f6322562b634 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 12 Aug 2020 02:33:56 -0400 Subject: [PATCH] Cherry-pick PR #39702 into release-4.0 (#39985) Component commits: cd5dde5d79 Improve deprecated suggestion node position 6e39ee706e fix typo a593fd03fe Simplify code 58f6f3daf2 merge helper function Co-authored-by: kingwl --- src/compiler/checker.ts | 34 ++++++++++++++++--- .../fourslash/jsdocDeprecated_suggestion1.ts | 31 ++++++++--------- .../fourslash/jsdocDeprecated_suggestion2.ts | 16 ++++----- .../fourslash/jsdocDeprecated_suggestion3.ts | 8 ++--- 4 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 748cab985dab1..43e9b4e5a67e0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24698,7 +24698,7 @@ namespace ts { if (isNodeOpeningLikeElement) { const jsxOpeningLikeNode = node as JsxOpeningLikeElement; const sig = getResolvedSignature(jsxOpeningLikeNode); - checkDeprecatedSignature(sig, node); + checkDeprecatedSignature(sig, node); checkJsxReturnAssignableToAppropriateBound(getJsxReferenceKind(jsxOpeningLikeNode), getReturnTypeOfSignature(sig), jsxOpeningLikeNode); } } @@ -27581,9 +27581,34 @@ namespace ts { return returnType; } - function checkDeprecatedSignature(signature: Signature, node: Node) { + function checkDeprecatedSignature(signature: Signature, node: CallLikeExpression) { if (signature.declaration && signature.declaration.flags & NodeFlags.Deprecated) { - errorOrSuggestion(/*isError*/ false, node, Diagnostics._0_is_deprecated, signatureToString(signature)); + const suggestionNode = getDeprecatedSuggestionNode(node); + errorOrSuggestion(/*isError*/ false, suggestionNode, Diagnostics._0_is_deprecated, signatureToString(signature)); + } + } + + function getDeprecatedSuggestionNode(node: Node): Node { + node = skipParentheses(node); + switch (node.kind) { + case SyntaxKind.CallExpression: + case SyntaxKind.Decorator: + case SyntaxKind.NewExpression: + return getDeprecatedSuggestionNode((node).expression); + case SyntaxKind.TaggedTemplateExpression: + return getDeprecatedSuggestionNode((node).tag); + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxSelfClosingElement: + return getDeprecatedSuggestionNode((node).tagName); + case SyntaxKind.ElementAccessExpression: + return (node).argumentExpression; + case SyntaxKind.PropertyAccessExpression: + return (node).name; + case SyntaxKind.TypeReference: + const typeReference = node; + return isQualifiedName(typeReference.typeName) ? typeReference.typeName.right : typeReference; + default: + return node; } } @@ -30978,8 +31003,7 @@ namespace ts { const symbol = getNodeLinks(node).resolvedSymbol; if (symbol) { if (some(symbol.declarations, d => isTypeDeclaration(d) && !!(d.flags & NodeFlags.Deprecated))) { - const diagLocation = isTypeReferenceNode(node) && isQualifiedName(node.typeName) ? node.typeName.right : node; - errorOrSuggestion(/* isError */ false, diagLocation, Diagnostics._0_is_deprecated, symbol.escapedName as string); + errorOrSuggestion(/* isError */ false, getDeprecatedSuggestionNode(node), Diagnostics._0_is_deprecated, symbol.escapedName as string); } if (type.flags & TypeFlags.Enum && symbol.flags & SymbolFlags.EnumMember) { error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type)); diff --git a/tests/cases/fourslash/jsdocDeprecated_suggestion1.ts b/tests/cases/fourslash/jsdocDeprecated_suggestion1.ts index 5725870f0fbb5..a0911eeea2a6d 100644 --- a/tests/cases/fourslash/jsdocDeprecated_suggestion1.ts +++ b/tests/cases/fourslash/jsdocDeprecated_suggestion1.ts @@ -5,18 +5,18 @@ //// export namespace foo { //// /** @deprecated */ //// export function faff () { } -//// [|faff()|] +//// [|faff|]() //// } -//// const [|a|] = [|foo.faff()|] +//// const [|a|] = foo.[|faff|]() //// foo[[|"faff"|]] //// const { [|faff|] } = foo -//// [|faff()|] +//// [|faff|]() //// /** @deprecated */ //// export function bar () { -//// [|foo?.faff()|] +//// foo?.[|faff|]() //// } -//// [|foo?.["faff"]?.()|] -//// [|bar()|]; +//// foo?.[[|"faff"|]]?.() +//// [|bar|](); //// /** @deprecated */ //// export interface Foo { //// /** @deprecated */ @@ -37,8 +37,8 @@ //// constructor() { //// } //// } -//// var c = [|new C()|] -//// [|c.m()|] +//// var c = new [|C|]() +//// c.[|m|]() //// c.[|m|] //// new [|D|]() //// C @@ -51,26 +51,26 @@ //// return
//// } //// [|Compi|]; -//// [||]; -//// [||]
; +//// <[|Compi|] />; +//// <[|Compi|] {...props}>
; //// /** @deprecated */ //// function ttf(_x: unknown) { //// } -//// [|ttf``|] +//// [|ttf|]`` //// [|ttf|] //// /** @deprecated */ //// function dec(_c: unknown) { } //// [|dec|] -//// [|@dec|] +//// @[|dec|] //// class K { } // @Filename: b.ts //// // imports and aliases //// import * as f from './a'; //// import { [|bar|], [|QW|] } from './a'; -//// [|f.bar()|]; -//// [|f.foo.faff()|]; -//// [|bar()|]; +//// f.[|bar|](); +//// f.foo.[|faff|](); +//// [|bar|](); //// type Z = [|QW|]; //// type A = f.[|Foo|]; //// type B = f.[|QW|]; @@ -79,7 +79,6 @@ goTo.file('a.ts') const ranges = test.ranges(); - verify.getSuggestionDiagnostics([ { "code": 6385, diff --git a/tests/cases/fourslash/jsdocDeprecated_suggestion2.ts b/tests/cases/fourslash/jsdocDeprecated_suggestion2.ts index 5f1560f08c238..e2c8b6233c959 100644 --- a/tests/cases/fourslash/jsdocDeprecated_suggestion2.ts +++ b/tests/cases/fourslash/jsdocDeprecated_suggestion2.ts @@ -5,20 +5,20 @@ //// /** @deprecated */ //// declare function foo(): undefined; //// declare function foo (a?: string): number | undefined; -//// [|foo()|]; +//// [|foo|](); //// foo(''); //// foo; //// /** @deprecated */ //// declare function bar(): number; -//// [|bar()|]; +//// [|bar|](); //// [|bar|]; //// /** @deprecated */ //// declare function baz(): number; //// /** @deprecated */ //// declare function baz(): number | undefined; -//// [|baz()|]; +//// [|baz|](); //// [|baz|]; //// interface Foo { @@ -27,7 +27,7 @@ //// (a: number): void //// } //// declare const f: Foo; -//// [|f()|]; +//// [|f|](); //// f(1); //// interface T { @@ -37,7 +37,7 @@ //// } //// declare const t: T; //// t.createElement(); -//// [|t.createElement('xmp')|]; +//// t.[|createElement|]('xmp'); //// declare class C { //// /** @deprecated */ @@ -45,7 +45,7 @@ //// constructor(v: string) //// } //// C; -//// const c = [|new C()|]; +//// const c = new [|C|](); //// interface Ca { //// /** @deprecated */ @@ -61,10 +61,10 @@ //// declare const cb: Cb; //// ca; //// cb; -//// [|ca()|]; +//// [|ca|](); //// cb(); //// new ca(); -//// [|new cb()|]; +//// new [|cb|](); const ranges = test.ranges(); verify.getSuggestionDiagnostics([ diff --git a/tests/cases/fourslash/jsdocDeprecated_suggestion3.ts b/tests/cases/fourslash/jsdocDeprecated_suggestion3.ts index 829060345fe22..4b3d32f7f10a7 100644 --- a/tests/cases/fourslash/jsdocDeprecated_suggestion3.ts +++ b/tests/cases/fourslash/jsdocDeprecated_suggestion3.ts @@ -13,7 +13,7 @@ //// declare function b(): void //// declare const tb: b; //// [|b|] -//// [|b()|]; +//// [|b|](); //// interface c { } //// /** @deprecated */ @@ -21,7 +21,7 @@ //// declare function c(a: number): void //// declare const tc: c; //// c; -//// [|c()|]; +//// [|c|](); //// c(1); //// /** @deprecated */ @@ -38,8 +38,8 @@ //// /** @deprecated */ //// declare function e(a: number): void //// [|e|]; -//// [|e()|]; -//// [|e(1)|]; +//// [|e|](); +//// [|e|](1); //// /** @deprecated */ //// interface f { a: number }