From 551400db8597f63a4f2ae9de050a3f1deee5b86a Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Sat, 14 Oct 2017 00:23:54 +0200 Subject: [PATCH] deprecation: properly check destructuring --- src/rules/deprecationRule.ts | 19 +++++++++++++++++-- test/rules/deprecation/test.ts.lint | 25 +++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/rules/deprecationRule.ts b/src/rules/deprecationRule.ts index a6847921ded..894ae8d2b8a 100644 --- a/src/rules/deprecationRule.ts +++ b/src/rules/deprecationRule.ts @@ -23,6 +23,9 @@ import { isIdentifier, isNewExpression, isPropertyAccessExpression, + isPropertyAssignment, + isReassignmentTarget, + isShorthandPropertyAssignment, isTaggedTemplateExpression, isVariableDeclaration, isVariableDeclarationList, @@ -102,10 +105,12 @@ function isDeclaration(identifier: ts.Identifier): boolean { case ts.SyntaxKind.VariableDeclaration: case ts.SyntaxKind.Parameter: case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertyAssignment: case ts.SyntaxKind.EnumMember: case ts.SyntaxKind.ImportEqualsDeclaration: return (parent as ts.NamedDeclaration).name === identifier; + case ts.SyntaxKind.PropertyAssignment: + return (parent as ts.PropertyAssignment).name === identifier && + !isReassignmentTarget(identifier.parent!.parent as ts.ObjectLiteralExpression); case ts.SyntaxKind.BindingElement: // return true for `b` in `const {a: b} = obj"` return (parent as ts.BindingElement).name === identifier && @@ -134,7 +139,17 @@ function getDeprecation(node: ts.Identifier, tc: ts.TypeChecker): string | undef return result; } } - let symbol = tc.getSymbolAtLocation(node); + let symbol: ts.Symbol | undefined; + const parent = node.parent!; + if (parent.kind === ts.SyntaxKind.BindingElement) { + symbol = tc.getTypeAtLocation(parent.parent!).getProperty(node.text); + } else if (isPropertyAssignment(parent) && parent.name === node || + isShorthandPropertyAssignment(parent) && parent.name === node && isReassignmentTarget(node)) { + symbol = tc.getPropertySymbolOfDestructuringAssignment(node); + } else { + symbol = tc.getSymbolAtLocation(node); + } + if (symbol !== undefined && Lint.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias)) { symbol = tc.getAliasedSymbol(symbol); } diff --git a/test/rules/deprecation/test.ts.lint b/test/rules/deprecation/test.ts.lint index 717a627a304..20a8c1d2330 100644 --- a/test/rules/deprecation/test.ts.lint +++ b/test/rules/deprecation/test.ts.lint @@ -143,9 +143,30 @@ import {DeprecatedClass, DeprecatedConstructorClass, PartiallyDeprecatedClass} f ~~~~~~~~~~~~~~~~~~~~~~~~ [err % ('PartiallyDeprecatedClass')] } -// TODO: those should be an error let {f, g, h} = p; -(function ({f, g}: I) {}) + ~ [err % ('f')] + ~ [errmsg % ('h', 'Use g instead.')] +({f, g, h} = p); + ~ [err % ('f')] + ~ [errmsg % ('h', 'Use g instead.')] + +({f: g, g: h, h: f} = p); + ~ [err % ('f')] + ~ [errmsg % ('h', 'Use g instead.')] + +{ + /** @deprecated Just don't use. */ + let tmp; + ({f: tmp} = p); + ~ [err % ('f')] + ~~~ [errmsg % ('tmp', "Just don't use.")] +} + +(function ({f, g, h: tmp}: I) {}) + ~ [err % ('f')] + ~ [errmsg % ('h', 'Use g instead.')] +(function ({foo: {f, g}}: {foo: I}) {}) + ~ [err % ('f')] [err]: %s is deprecated. [errmsg]: %s is deprecated: %s