Compare commits
4 commits
main
...
report-dep
Author | SHA1 | Date | |
---|---|---|---|
|
1089cd156c | ||
|
a9d808bd0d | ||
|
52a175bd6d | ||
|
5a06bd3c73 |
|
@ -27134,6 +27134,17 @@ namespace ts {
|
||||||
symbolToString(member), typeToString(contextualType));
|
symbolToString(member), typeToString(contextualType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (contextualType) {
|
||||||
|
const contextualProperty = getPropertyOfType(contextualType, member.escapedName)
|
||||||
|
const isFromOverload = contextualProperty?.declarations?.some(decl => {
|
||||||
|
const param = findAncestor(decl, isParameter)
|
||||||
|
return param && isFunctionDeclaration(param.parent) && countWhere(getSymbolOfNode(param.parent).declarations, isFunctionLike) > 1
|
||||||
|
})
|
||||||
|
if (!isFromOverload) {
|
||||||
|
checkDeprecatedProperty(member, contextualProperty)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
prop.declarations = member.declarations;
|
prop.declarations = member.declarations;
|
||||||
prop.parent = member.parent;
|
prop.parent = member.parent;
|
||||||
|
@ -27845,10 +27856,17 @@ namespace ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNodeOpeningLikeElement) {
|
if (isNodeOpeningLikeElement) {
|
||||||
const jsxOpeningLikeNode = node as JsxOpeningLikeElement;
|
const sig = getResolvedSignature(node);
|
||||||
const sig = getResolvedSignature(jsxOpeningLikeNode);
|
checkDeprecatedSignature(sig, node);
|
||||||
checkDeprecatedSignature(sig, node as JsxOpeningLikeElement);
|
const param = sig.parameters[0]
|
||||||
checkJsxReturnAssignableToAppropriateBound(getJsxReferenceKind(jsxOpeningLikeNode), getReturnTypeOfSignature(sig), jsxOpeningLikeNode);
|
for (const source of node.attributes.properties) {
|
||||||
|
const member = source.symbol;
|
||||||
|
const attributesTarget = getTypeOfSymbol(param)
|
||||||
|
if (member && attributesTarget) {
|
||||||
|
checkDeprecatedProperty(member, getPropertyOfType(attributesTarget, member.escapedName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkJsxReturnAssignableToAppropriateBound(getJsxReferenceKind(node), getReturnTypeOfSignature(sig), node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31072,6 +31090,16 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkDeprecatedProperty(source: Symbol, target: Symbol | undefined) {
|
||||||
|
if (target?.declarations?.some(decl => decl.flags & NodeFlags.Deprecated)) {
|
||||||
|
const node = source.valueDeclaration!;
|
||||||
|
const nameNode = isPropertyAssignment(node) || isShorthandPropertyAssignment(node) || isObjectLiteralMethod(node) || isJsxAttribute(node)
|
||||||
|
? node.name
|
||||||
|
: source.valueDeclaration!;
|
||||||
|
addDeprecatedSuggestion(nameNode, target.declarations, source.escapedName as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getDeprecatedSuggestionNode(node: Node): Node {
|
function getDeprecatedSuggestionNode(node: Node): Node {
|
||||||
node = skipParentheses(node);
|
node = skipParentheses(node);
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
//// interface Props {
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// foo?: string;
|
||||||
|
//// bar: string;
|
||||||
|
//// baz?: {
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// foo?: boolean;
|
||||||
|
//// bar?: boolean;
|
||||||
|
//// };
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// callback?: () => void
|
||||||
|
//// }
|
||||||
|
//// const Component = (props: Props) => props && <div />;
|
||||||
|
//// const foo = "foo";
|
||||||
|
//// const bar = "bar";
|
||||||
|
//// const callback = () => {};
|
||||||
|
|
||||||
|
//// let props: Props = { [|callback|]: () => {}, [|foo|]: "foo", bar: "bar", baz: { [|foo|]: true } };
|
||||||
|
//// props = { [|"foo"|]: "foo", "bar": "bar" };
|
||||||
|
//// props = { [|["foo"]|]: "foo", ["bar"]: "bar" };
|
||||||
|
//// props = { [|foo|], bar, [|callback|] };
|
||||||
|
//// props = { bar, [|callback|]() {} };
|
||||||
|
|
||||||
|
//// // Skip if there is a type incompatibility error.
|
||||||
|
//// const props5: Props = { [|foo|]: "foo", boo: "boo" };
|
||||||
|
|
||||||
|
//// // Skip for union types.
|
||||||
|
//// const props6: { foo: { /** @deprecated */ bar: string } | { bar: string, baz: string } } = { foo: { bar: "bar" } };
|
||||||
|
|
||||||
|
const ranges = test.ranges();
|
||||||
|
|
||||||
|
verify.getSuggestionDiagnostics([
|
||||||
|
{
|
||||||
|
message: "'callback' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[0],
|
||||||
|
reportsDeprecated: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[1],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[2],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[3],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[4],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[5],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'callback' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[6],
|
||||||
|
reportsDeprecated: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'callback' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[7],
|
||||||
|
reportsDeprecated: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[8],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
])
|
|
@ -0,0 +1,88 @@
|
||||||
|
//// interface Props {
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// foo?: string;
|
||||||
|
//// bar: string;
|
||||||
|
//// baz?: {
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// foo?: boolean;
|
||||||
|
//// bar?: boolean;
|
||||||
|
//// };
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// callback?: () => void
|
||||||
|
//// }
|
||||||
|
//// const func = (_props: Props) => {};
|
||||||
|
//// const foo = "foo";
|
||||||
|
//// const bar = "bar";
|
||||||
|
//// const callback = () => {};
|
||||||
|
|
||||||
|
//// func({ [|callback|]: () => {}, [|foo|]: "foo", bar: "bar", baz: { [|foo|]: true } });
|
||||||
|
//// func({ [|"foo"|]: "foo", "bar": "bar" });
|
||||||
|
//// func({ [|["foo"]|]: "foo", ["bar"]: "bar" });
|
||||||
|
//// func({ [|foo|], bar, [|callback|] });
|
||||||
|
//// func({ bar, [|callback|]() {} });
|
||||||
|
|
||||||
|
//// // Do not skip if there is a type incompatibility error.
|
||||||
|
//// func({ [|foo|]: "foo", boo: "boo" });
|
||||||
|
|
||||||
|
//// // Skip for union types.
|
||||||
|
//// function test(_args: { foo: { /** @deprecated */ bar: string } | { bar: string, baz: string } }) {}
|
||||||
|
//// test({ foo: { bar: "bar" } })
|
||||||
|
|
||||||
|
const ranges = test.ranges();
|
||||||
|
|
||||||
|
verify.getSuggestionDiagnostics([
|
||||||
|
{
|
||||||
|
message: "'callback' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[0],
|
||||||
|
reportsDeprecated: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[1],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[2],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[3],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[4],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[5],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'callback' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[6],
|
||||||
|
reportsDeprecated: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'callback' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[7],
|
||||||
|
reportsDeprecated: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[8],
|
||||||
|
reportsDeprecated: true,
|
||||||
|
},
|
||||||
|
])
|
|
@ -0,0 +1,80 @@
|
||||||
|
/// <reference path="fourslash.ts" />
|
||||||
|
// @Filename: a.tsx
|
||||||
|
//// type Props = {
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// foo?: string;
|
||||||
|
//// bar: string;
|
||||||
|
//// baz?: {
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// foo?: boolean;
|
||||||
|
//// bar?: boolean;
|
||||||
|
//// };
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// callback?: () => void
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// bool?: boolean;
|
||||||
|
//// }
|
||||||
|
//// const Component = (props: Props) => props && <div />;
|
||||||
|
//// const foo = "foo";
|
||||||
|
//// const bar = "bar";
|
||||||
|
|
||||||
|
//// <Component [|bool|] [|callback|]={() => {}} [|foo|]="foo" bar="bar" baz={{ [|foo|]: true }} />;
|
||||||
|
|
||||||
|
//// // Do not skip spread in jsx
|
||||||
|
//// <Component {...{ [|foo|]: "foo", bar: "bar" }} />;
|
||||||
|
|
||||||
|
//// // Do not skip if there is a type incompatibility error.
|
||||||
|
//// <Component [|foo|]="" boo="" />;
|
||||||
|
//// <Component {...{ [|foo|]: "foo", boo: "boo" }} />;
|
||||||
|
|
||||||
|
//// // Skip for union types.
|
||||||
|
//// const Component2 = (_props: { foo: { /** @deprecated */ bar: string } | { bar: string, baz: string } }) => <div />;
|
||||||
|
//// <Component2 foo={{ bar: "bar" }} />;
|
||||||
|
|
||||||
|
goTo.file('a.tsx')
|
||||||
|
const ranges = test.ranges();
|
||||||
|
|
||||||
|
verify.getSuggestionDiagnostics([
|
||||||
|
{
|
||||||
|
message: "'bool' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[0],
|
||||||
|
reportsDeprecated: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'callback' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[1],
|
||||||
|
reportsDeprecated: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[2],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[3],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[4],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[5],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "'foo' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[6],
|
||||||
|
reportsDeprecated: true as const,
|
||||||
|
},
|
||||||
|
])
|
|
@ -0,0 +1,25 @@
|
||||||
|
// @Filename: a.tsx
|
||||||
|
//// function OverridableComponent(props: {
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// a: boolean;
|
||||||
|
//// c?: boolean;
|
||||||
|
//// }): JSX.Element
|
||||||
|
//// function OverridableComponent(props: { a: boolean; b: boolean }): JSX.Element
|
||||||
|
//// function OverridableComponent(_props: { a: boolean; b?: boolean; c?: boolean }) {
|
||||||
|
//// return <div />;
|
||||||
|
//// }
|
||||||
|
|
||||||
|
//// <OverridableComponent [|a|] />;
|
||||||
|
//// <OverridableComponent a b />;
|
||||||
|
|
||||||
|
goTo.file('a.tsx')
|
||||||
|
const ranges = test.ranges();
|
||||||
|
|
||||||
|
verify.getSuggestionDiagnostics([
|
||||||
|
{
|
||||||
|
message: "'a' is deprecated.",
|
||||||
|
code: 6385,
|
||||||
|
range: ranges[0],
|
||||||
|
reportsDeprecated: true,
|
||||||
|
}
|
||||||
|
])
|
|
@ -0,0 +1,16 @@
|
||||||
|
//// function overloadFunc(props: {
|
||||||
|
//// /** @deprecated */
|
||||||
|
//// a: boolean;
|
||||||
|
//// c?: boolean;
|
||||||
|
//// }): JSX.Element
|
||||||
|
//// function overloadFunc(props: { a: boolean; b: boolean }): JSX.Element
|
||||||
|
//// function overloadFunc(_props: { a: boolean; b?: boolean; c?: boolean }) {
|
||||||
|
//// return <div />;
|
||||||
|
//// }
|
||||||
|
|
||||||
|
//// overloadFunc({ [|a|]: true });
|
||||||
|
//// overloadFunc({ a: true, b: true });
|
||||||
|
|
||||||
|
const ranges = test.ranges();
|
||||||
|
|
||||||
|
verify.getSuggestionDiagnostics([])
|
Loading…
Reference in a new issue