From 327d0d809ef2c61fa5387cf8a4164f47e9ae3e4e Mon Sep 17 00:00:00 2001 From: Adi Dahiya Date: Wed, 10 Aug 2022 16:08:30 -0400 Subject: [PATCH 1/6] [eslint-plugin] feat: only lint MenuItem with popoverProps attr --- .../createNoDeprecatedComponentsRule.ts | 105 +++++++++++++++--- .../no-deprecated-core-components.ts | 2 +- packages/eslint-plugin/test/index.ts | 1 + .../no-deprecated-core-components.test.ts | 91 +++++++++++++++ 4 files changed, 180 insertions(+), 19 deletions(-) create mode 100644 packages/eslint-plugin/test/no-deprecated-core-components.test.ts diff --git a/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts b/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts index edb0b4109a..2818889bb8 100644 --- a/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts +++ b/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts @@ -8,15 +8,15 @@ import { TSESLint, TSESTree } from "@typescript-eslint/utils"; import { createRule } from "../utils/createRule"; -type MessageIds = "migration"; +type MessageIds = "migration" | "migrationWithPropUsage"; /** * Higher-order function to create an ESLint rule which checks for usage of deprecated React components * in JSX syntax. * - * Only components imported from `packagesToCheck` will be flagged. The lint violation will include - * a recommendation to migrate to the newer, non-deprecated component (this must be specified for each - * component via the second argument `deprecatedToNewComponentMapping`). + * @param packagesToCheck Only components imported from these packages will be flagged. + * @param deprecatedToNewComponentMapping Lint violations will include a recommendation to migrate to the newer, + * non-deprecated component specified in this mapping. Keys in this object may use */ export function createNoDeprecatedComponentsRule( ruleName: string, @@ -37,11 +37,14 @@ export function createNoDeprecatedComponentsRule( recommended: "error", }, messages: { - migration: "{{ deprecatedComponentName }} is deprecated, migrate to {{ newComponentName }} instead", + migration: + "Usage of {{ deprecatedComponentName }} is deprecated, migrate to {{ newComponentName }} instead", + migrationWithPropUsage: + "Usage of {{ deprecatedComponentName }} with prop '{{ deprecatedPropName }}' is deprecated, migrate to {{ newComponentName }} instead", }, schema: [ { - enum: ["migration"], + enum: ["migration", "migrationWithPropUsage"], }, ], }, @@ -52,24 +55,35 @@ export function createNoDeprecatedComponentsRule( | { type: "function"; functionName: string; localFunctionName: string } > = []; + // parses out additional deprecated components from entries like { "MenuItem.popoverProps": "MenuItem2" } + const additionalDeprecatedComponents = Object.keys(deprecatedToNewComponentMapping).reduce( + (components, key) => { + const [componentName, propName] = key.split("."); + if (propName !== undefined) { + components.push(componentName); + } + return components; + }, + [], + ); + function isDeprecatedComponent(name: string) { - if (deprecatedImports.length === 0) { - return false; - } - - return deprecatedImports.some( - deprecatedImport => - (deprecatedImport.type === "function" && deprecatedImport.localFunctionName === name) || - deprecatedToNewComponentMapping[name] != null, + return ( + deprecatedToNewComponentMapping[name] != null && + deprecatedImports.some( + deprecatedImport => + deprecatedImport.type === "function" && deprecatedImport.localFunctionName === name, + ) ); } function isDeprecatedNamespacedComponent(name: string, property: string) { return ( + deprecatedToNewComponentMapping[property] != null && deprecatedImports.some( deprecatedImport => deprecatedImport.type === "namespace" && deprecatedImport.namespace === name, - ) && deprecatedToNewComponentMapping[property] != null + ) ); } @@ -89,7 +103,10 @@ export function createNoDeprecatedComponentsRule( }); break; case TSESTree.AST_NODE_TYPES.ImportSpecifier: - if (deprecatedToNewComponentMapping[importClause.imported.name] != null) { + if ( + deprecatedToNewComponentMapping[importClause.imported.name] != null || + additionalDeprecatedComponents.includes(importClause.imported.name) + ) { deprecatedImports.push({ functionName: importClause.imported.name, localFunctionName: importClause.local.name, @@ -101,7 +118,7 @@ export function createNoDeprecatedComponentsRule( } }, - // check syntax + // check syntax (includes self-closing tags) "JSXElement > JSXOpeningElement > JSXIdentifier": (node: TSESTree.JSXIdentifier) => { if (isDeprecatedComponent(node.name)) { context.report({ @@ -112,10 +129,34 @@ export function createNoDeprecatedComponentsRule( messageId: "migration", node, }); + } else if (isOpeningElement(node.parent)) { + // check syntax + const deprecatedProp = node.parent.attributes.find( + attribute => + attribute.type === TSESTree.AST_NODE_TYPES.JSXAttribute && + attribute.name.type === TSESTree.AST_NODE_TYPES.JSXIdentifier && + deprecatedToNewComponentMapping[`${node.name}.${attribute.name.name}`] != null, + ); + if (deprecatedProp !== undefined) { + const deprecatedComponentKey = Object.keys(deprecatedToNewComponentMapping).find( + key => key.split(".")[0] === node.name, + ); + context.report({ + data: { + deprecatedComponentName: node.name, + deprecatedPropName: ( + (deprecatedProp as TSESTree.JSXAttribute).name as TSESTree.JSXIdentifier + ).name, + newComponentName: deprecatedToNewComponentMapping[deprecatedComponentKey!], + }, + messageId: "migrationWithPropUsage", + node, + }); + } } }, - // check syntax + // check syntax (includes self-closing tags) "JSXElement > JSXOpeningElement > JSXMemberExpression[property.type='JSXIdentifier']": ( node: TSESTree.JSXMemberExpression, ) => { @@ -137,6 +178,30 @@ export function createNoDeprecatedComponentsRule( messageId: "migration", node: node.property, }); + } else if (isOpeningElement(node.parent)) { + // check syntax + const deprecatedProp = node.parent.attributes.find( + attribute => + attribute.type === TSESTree.AST_NODE_TYPES.JSXAttribute && + attribute.name.type === TSESTree.AST_NODE_TYPES.JSXIdentifier && + deprecatedToNewComponentMapping[`${node.property.name}.${attribute.name.name}`] != null, + ); + if (deprecatedProp !== undefined) { + const deprecatedComponentKey = Object.keys(deprecatedToNewComponentMapping).find( + key => key.split(".")[0] === node.property.name, + ); + context.report({ + data: { + deprecatedComponentName: node.property.name, + deprecatedPropName: ( + (deprecatedProp as TSESTree.JSXAttribute).name as TSESTree.JSXIdentifier + ).name, + newComponentName: deprecatedToNewComponentMapping[deprecatedComponentKey!], + }, + messageId: "migrationWithPropUsage", + node, + }); + } } }, @@ -182,3 +247,7 @@ export function createNoDeprecatedComponentsRule( }, }); } + +function isOpeningElement(parent: TSESTree.Node | undefined): parent is TSESTree.JSXOpeningElement { + return parent?.type === TSESTree.AST_NODE_TYPES.JSXOpeningElement; +} diff --git a/packages/eslint-plugin/src/rules/no-deprecated-components/no-deprecated-core-components.ts b/packages/eslint-plugin/src/rules/no-deprecated-components/no-deprecated-core-components.ts index a9481d41c1..76e984d8bc 100644 --- a/packages/eslint-plugin/src/rules/no-deprecated-components/no-deprecated-core-components.ts +++ b/packages/eslint-plugin/src/rules/no-deprecated-components/no-deprecated-core-components.ts @@ -9,7 +9,7 @@ export const coreComponentsMigrationMapping = { AbstractPureComponent: "AbstractPureComponent2", Breadcrumbs: "Breadcrumbs2", CollapsibleList: "OverflowList", - MenuItem: "MenuItem2", + "MenuItem.popoverProps": "MenuItem2", PanelStack: "PanelStack2", Popover: "Popover2", Tooltip: "Tooltip2", diff --git a/packages/eslint-plugin/test/index.ts b/packages/eslint-plugin/test/index.ts index 9c6932dde5..53b5279310 100644 --- a/packages/eslint-plugin/test/index.ts +++ b/packages/eslint-plugin/test/index.ts @@ -18,3 +18,4 @@ import "./classes-constants.test"; import "./html-components.test"; import "./icon-components.test"; import "./no-deprecated-components.test"; +import "./no-deprecated-core-components.test"; diff --git a/packages/eslint-plugin/test/no-deprecated-core-components.test.ts b/packages/eslint-plugin/test/no-deprecated-core-components.test.ts new file mode 100644 index 0000000000..ea2f9a929c --- /dev/null +++ b/packages/eslint-plugin/test/no-deprecated-core-components.test.ts @@ -0,0 +1,91 @@ +/* + * Copyright 2022 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// tslint:disable object-literal-sort-keys +/* eslint-disable no-template-curly-in-string */ + +import { TSESLint } from "@typescript-eslint/utils"; +import dedent from "dedent"; + +import { noDeprecatedCoreComponentsRule } from "../src/rules/no-deprecated-components"; + +const ruleTester = new TSESLint.RuleTester({ + parser: require.resolve("@typescript-eslint/parser"), + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + sourceType: "module", + }, +}); + +console.info("Testing no-deprecated-core-components rule..."); +ruleTester.run("no-deprecated-core-components", noDeprecatedCoreComponentsRule, { + // N.B. most other deprecated components are tested by no-deprecated-components.test.ts, this suite just tests + // for more specific violations which involve certain deprecated props + invalid: [ + { + code: dedent` + import { MenuItem } from "@blueprintjs/core"; + + return + `, + errors: [ + { + messageId: "migrationWithPropUsage", + data: { + deprecatedComponentName: "MenuItem", + deprecatedPropName: "popoverProps", + newComponentName: "MenuItem2", + }, + }, + ], + }, + { + code: dedent` + import * as Blueprint from "@blueprintjs/core"; + + return + `, + errors: [ + { + messageId: "migrationWithPropUsage", + data: { + deprecatedComponentName: "MenuItem", + deprecatedPropName: "popoverProps", + newComponentName: "MenuItem2", + }, + }, + ], + }, + ], + valid: [ + { + code: dedent` + import { MenuItem } from "@blueprintjs/core"; + + return + `, + }, + { + code: dedent` + import * as Blueprint from "@blueprintjs/core"; + + return + `, + }, + ], +}); From f3a1600aef7e40b66f5f7e4e1e421ddc94ade1bf Mon Sep 17 00:00:00 2001 From: Adi Dahiya Date: Wed, 10 Aug 2022 16:16:15 -0400 Subject: [PATCH 2/6] lint flag --- packages/core/test/menu/menuItemTests.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/test/menu/menuItemTests.tsx b/packages/core/test/menu/menuItemTests.tsx index fbd077f756..e8ad9383a6 100644 --- a/packages/core/test/menu/menuItemTests.tsx +++ b/packages/core/test/menu/menuItemTests.tsx @@ -19,7 +19,7 @@ * All changes & bugfixes should be made to MenuItem2 instead. */ -/* eslint-disable deprecation/deprecation */ +/* eslint-disable deprecation/deprecation @blueprintjs/no-deprecated-components */ import { assert } from "chai"; import { mount, ReactWrapper, shallow, ShallowWrapper } from "enzyme"; From 0bacb65da24f7cac555470d198a5fc0a9279ca67 Mon Sep 17 00:00:00 2001 From: Adi Dahiya Date: Wed, 10 Aug 2022 22:47:47 -0400 Subject: [PATCH 3/6] DRY rule implementation based on CR feedback --- .../createNoDeprecatedComponentsRule.ts | 78 ++++++++----------- 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts b/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts index 2818889bb8..a82ab13543 100644 --- a/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts +++ b/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts @@ -87,6 +87,38 @@ export function createNoDeprecatedComponentsRule( ); } + function checkDeprecatedComponentAndProp( + jsxOpeningElementChildNode: TSESTree.Node, + elementName: string, + openingElementNode: TSESTree.JSXOpeningElement, + ) { + const deprecatedProp = openingElementNode.attributes.find( + attribute => + attribute.type === TSESTree.AST_NODE_TYPES.JSXAttribute && + attribute.name.type === TSESTree.AST_NODE_TYPES.JSXIdentifier && + deprecatedToNewComponentMapping[`${elementName}.${attribute.name.name}`] != null, + ); + + if (deprecatedProp === undefined) { + return; + } + + const deprecatedComponentKey = Object.keys(deprecatedToNewComponentMapping).find( + key => key.includes(".") && key.split(".")[0] === elementName, + ); + const deprecatedPropName = ((deprecatedProp as TSESTree.JSXAttribute).name as TSESTree.JSXIdentifier) + .name; + context.report({ + data: { + deprecatedComponentName: elementName, + deprecatedPropName, + newComponentName: deprecatedToNewComponentMapping[deprecatedComponentKey!], + }, + messageId: "migrationWithPropUsage", + node: jsxOpeningElementChildNode, + }); + } + // Get the list of all deprecated imports from packages included in the provided list return { "Program > ImportDeclaration": (node: TSESTree.ImportDeclaration) => { @@ -131,28 +163,7 @@ export function createNoDeprecatedComponentsRule( }); } else if (isOpeningElement(node.parent)) { // check syntax - const deprecatedProp = node.parent.attributes.find( - attribute => - attribute.type === TSESTree.AST_NODE_TYPES.JSXAttribute && - attribute.name.type === TSESTree.AST_NODE_TYPES.JSXIdentifier && - deprecatedToNewComponentMapping[`${node.name}.${attribute.name.name}`] != null, - ); - if (deprecatedProp !== undefined) { - const deprecatedComponentKey = Object.keys(deprecatedToNewComponentMapping).find( - key => key.split(".")[0] === node.name, - ); - context.report({ - data: { - deprecatedComponentName: node.name, - deprecatedPropName: ( - (deprecatedProp as TSESTree.JSXAttribute).name as TSESTree.JSXIdentifier - ).name, - newComponentName: deprecatedToNewComponentMapping[deprecatedComponentKey!], - }, - messageId: "migrationWithPropUsage", - node, - }); - } + checkDeprecatedComponentAndProp(node, node.name, node.parent); } }, @@ -180,28 +191,7 @@ export function createNoDeprecatedComponentsRule( }); } else if (isOpeningElement(node.parent)) { // check syntax - const deprecatedProp = node.parent.attributes.find( - attribute => - attribute.type === TSESTree.AST_NODE_TYPES.JSXAttribute && - attribute.name.type === TSESTree.AST_NODE_TYPES.JSXIdentifier && - deprecatedToNewComponentMapping[`${node.property.name}.${attribute.name.name}`] != null, - ); - if (deprecatedProp !== undefined) { - const deprecatedComponentKey = Object.keys(deprecatedToNewComponentMapping).find( - key => key.split(".")[0] === node.property.name, - ); - context.report({ - data: { - deprecatedComponentName: node.property.name, - deprecatedPropName: ( - (deprecatedProp as TSESTree.JSXAttribute).name as TSESTree.JSXIdentifier - ).name, - newComponentName: deprecatedToNewComponentMapping[deprecatedComponentKey!], - }, - messageId: "migrationWithPropUsage", - node, - }); - } + checkDeprecatedComponentAndProp(node, node.property.name, node.parent); } }, From 11aae1f72cdbf761f28bc7ec9cd5c2fc37a9c20c Mon Sep 17 00:00:00 2001 From: Adi Dahiya Date: Wed, 10 Aug 2022 22:58:42 -0400 Subject: [PATCH 4/6] fix lint flag --- packages/core/test/menu/menuItemTests.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/test/menu/menuItemTests.tsx b/packages/core/test/menu/menuItemTests.tsx index e8ad9383a6..04279645be 100644 --- a/packages/core/test/menu/menuItemTests.tsx +++ b/packages/core/test/menu/menuItemTests.tsx @@ -19,7 +19,7 @@ * All changes & bugfixes should be made to MenuItem2 instead. */ -/* eslint-disable deprecation/deprecation @blueprintjs/no-deprecated-components */ +/* eslint-disable deprecation/deprecation */ import { assert } from "chai"; import { mount, ReactWrapper, shallow, ShallowWrapper } from "enzyme"; @@ -149,6 +149,7 @@ describe("MenuItem", () => { popoverClassName: "CUSTOM_POPOVER_CLASS_NAME", }; const wrapper = shallow( + // eslint-disable-next-line @blueprintjs/no-deprecated-components From 0cdad061ee18d95a5b2ef7d7c3b6bca57b3832f1 Mon Sep 17 00:00:00 2001 From: Adi Dahiya Date: Wed, 10 Aug 2022 23:21:29 -0400 Subject: [PATCH 5/6] fix bad merge --- .../no-deprecated-components/no-deprecated-core-components.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/no-deprecated-components/no-deprecated-core-components.ts b/packages/eslint-plugin/src/rules/no-deprecated-components/no-deprecated-core-components.ts index 1a6b4d7c5a..098177072d 100644 --- a/packages/eslint-plugin/src/rules/no-deprecated-components/no-deprecated-core-components.ts +++ b/packages/eslint-plugin/src/rules/no-deprecated-components/no-deprecated-core-components.ts @@ -9,7 +9,7 @@ export const coreComponentsMigrationMapping = { AbstractPureComponent: "AbstractPureComponent2", Breadcrumbs: "Breadcrumbs2", CollapsibleList: "OverflowList", - MenuItem: "MenuItem2", + "MenuItem.popoverProps": "MenuItem2", // TODO(@adidahiya): Blueprint v6 // PanelStack: "PanelStack2", Popover: "Popover2", From bb8113f8501c81c792cc661c7e6e601e25ab3bbf Mon Sep 17 00:00:00 2001 From: Adi Dahiya Date: Thu, 11 Aug 2022 10:33:24 -0400 Subject: [PATCH 6/6] minor rule documentation fix --- .../createNoDeprecatedComponentsRule.ts | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts b/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts index a82ab13543..fa99a2b6a9 100644 --- a/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts +++ b/packages/eslint-plugin/src/rules/no-deprecated-components/createNoDeprecatedComponentsRule.ts @@ -11,19 +11,23 @@ import { createRule } from "../utils/createRule"; type MessageIds = "migration" | "migrationWithPropUsage"; /** - * Higher-order function to create an ESLint rule which checks for usage of deprecated React components - * in JSX syntax. + * Higher-order function to create an ESLint rule which checks for usage of deprecated React components in JSX syntax. * * @param packagesToCheck Only components imported from these packages will be flagged. - * @param deprecatedToNewComponentMapping Lint violations will include a recommendation to migrate to the newer, - * non-deprecated component specified in this mapping. Keys in this object may use + * + * @param deprecatedComponentConfig Configuration of the deprecated components to lint for. Note that this configuration + * is not exposed to lint rule users, it just lives inside our rule implementations. Lint violations will include a + * recommendation to migrate to the newer, non-deprecated component specified in this mapping. Keys-value pairs may use + * one of two syntaxes: + * - "ComponentV1": "ComponentV2" - Usage of will be flagged with a recommendation + * to migrate to + * - "ComponentV1.propName": "ComponentV2" - Usage of will be flagged with a + * recommendation to migrate to */ export function createNoDeprecatedComponentsRule( ruleName: string, packagesToCheck: string[], - deprecatedToNewComponentMapping: { - [deprecated: string]: string; - }, + deprecatedComponentConfig: Record, ): TSESLint.RuleModule { const descriptionFromClause = packagesToCheck.length === 1 ? ` from ${packagesToCheck[0]}` : ""; @@ -56,7 +60,7 @@ export function createNoDeprecatedComponentsRule( > = []; // parses out additional deprecated components from entries like { "MenuItem.popoverProps": "MenuItem2" } - const additionalDeprecatedComponents = Object.keys(deprecatedToNewComponentMapping).reduce( + const additionalDeprecatedComponents = Object.keys(deprecatedComponentConfig).reduce( (components, key) => { const [componentName, propName] = key.split("."); if (propName !== undefined) { @@ -69,7 +73,7 @@ export function createNoDeprecatedComponentsRule( function isDeprecatedComponent(name: string) { return ( - deprecatedToNewComponentMapping[name] != null && + deprecatedComponentConfig[name] != null && deprecatedImports.some( deprecatedImport => deprecatedImport.type === "function" && deprecatedImport.localFunctionName === name, @@ -79,7 +83,7 @@ export function createNoDeprecatedComponentsRule( function isDeprecatedNamespacedComponent(name: string, property: string) { return ( - deprecatedToNewComponentMapping[property] != null && + deprecatedComponentConfig[property] != null && deprecatedImports.some( deprecatedImport => deprecatedImport.type === "namespace" && deprecatedImport.namespace === name, @@ -96,14 +100,14 @@ export function createNoDeprecatedComponentsRule( attribute => attribute.type === TSESTree.AST_NODE_TYPES.JSXAttribute && attribute.name.type === TSESTree.AST_NODE_TYPES.JSXIdentifier && - deprecatedToNewComponentMapping[`${elementName}.${attribute.name.name}`] != null, + deprecatedComponentConfig[`${elementName}.${attribute.name.name}`] != null, ); if (deprecatedProp === undefined) { return; } - const deprecatedComponentKey = Object.keys(deprecatedToNewComponentMapping).find( + const deprecatedComponentKey = Object.keys(deprecatedComponentConfig).find( key => key.includes(".") && key.split(".")[0] === elementName, ); const deprecatedPropName = ((deprecatedProp as TSESTree.JSXAttribute).name as TSESTree.JSXIdentifier) @@ -112,7 +116,7 @@ export function createNoDeprecatedComponentsRule( data: { deprecatedComponentName: elementName, deprecatedPropName, - newComponentName: deprecatedToNewComponentMapping[deprecatedComponentKey!], + newComponentName: deprecatedComponentConfig[deprecatedComponentKey!], }, messageId: "migrationWithPropUsage", node: jsxOpeningElementChildNode, @@ -136,7 +140,7 @@ export function createNoDeprecatedComponentsRule( break; case TSESTree.AST_NODE_TYPES.ImportSpecifier: if ( - deprecatedToNewComponentMapping[importClause.imported.name] != null || + deprecatedComponentConfig[importClause.imported.name] != null || additionalDeprecatedComponents.includes(importClause.imported.name) ) { deprecatedImports.push({ @@ -156,7 +160,7 @@ export function createNoDeprecatedComponentsRule( context.report({ data: { deprecatedComponentName: node.name, - newComponentName: deprecatedToNewComponentMapping[node.name], + newComponentName: deprecatedComponentConfig[node.name], }, messageId: "migration", node, @@ -184,7 +188,7 @@ export function createNoDeprecatedComponentsRule( context.report({ data: { deprecatedComponentName: node.property.name, - newComponentName: deprecatedToNewComponentMapping[node.property.name], + newComponentName: deprecatedComponentConfig[node.property.name], }, messageId: "migration", node: node.property, @@ -202,7 +206,7 @@ export function createNoDeprecatedComponentsRule( context.report({ data: { deprecatedComponentName: superClass.name, - newComponentName: deprecatedToNewComponentMapping[superClass.name], + newComponentName: deprecatedComponentConfig[superClass.name], }, messageId: "migration", node, @@ -226,7 +230,7 @@ export function createNoDeprecatedComponentsRule( context.report({ data: { deprecatedComponentName: superClass.property.name, - newComponentName: deprecatedToNewComponentMapping[superClass.property.name], + newComponentName: deprecatedComponentConfig[superClass.property.name], }, messageId: "migration", node: superClass.property,