Skip to content

Commit

Permalink
fix(no-deprecated-type-references): no overlapping import fixes (#5530)
Browse files Browse the repository at this point in the history
  • Loading branch information
adidahiya authored Sep 7, 2022
1 parent f9d5b41 commit 8ff2797
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 27 deletions.
2 changes: 1 addition & 1 deletion packages/eslint-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"lint": "run-p lint:es",
"lint:es": "es-lint",
"lint-fix": "es-lint --fix",
"test": "mocha test/index.ts"
"test": "mocha"
},
"dependencies": {
"@typescript-eslint/utils": "^5.32.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ export const noDeprecatedTypeReferencesRule = createRule<[], MessageIds>({
const deprecatedImports: Array<
{ namespace: string; type: "namespace" } | { type: "symbol"; symbolName: string; localSymbolName: string }
> = [];
// keep a list of already fixed imports in the file so that we do not report overlapping fixes
const fixedImportNames: string[] = [];

function isDeprecatedTypeReference(name: string) {
return (
Expand Down Expand Up @@ -260,7 +262,7 @@ export const noDeprecatedTypeReferencesRule = createRule<[], MessageIds>({
const fixes = new FixList();
fixes.addFixes(fixer.replaceText(node.typeName, newTypeName));
const program = getProgram(node);
if (program !== undefined) {
if (program !== undefined && !fixedImportNames.includes(deprecatedTypeName)) {
fixes.addFixes(
replaceImportInFile(
program,
Expand All @@ -269,6 +271,7 @@ export const noDeprecatedTypeReferencesRule = createRule<[], MessageIds>({
newTypeToPackageName[newTypeName],
)(fixer),
);
fixedImportNames.push(deprecatedTypeName);
}
return fixes.getFixes();
},
Expand All @@ -295,6 +298,7 @@ export const noDeprecatedTypeReferencesRule = createRule<[], MessageIds>({
}
},

// lint syntax like `interface MyInterface extends DeprecatedInterface {...}`
TSInterfaceHeritage: (node: TSESTree.TSInterfaceHeritage) => {
if (node.expression.type === TSESTree.AST_NODE_TYPES.Identifier) {
if (isDeprecatedTypeReference(node.expression.name)) {
Expand All @@ -308,7 +312,7 @@ export const noDeprecatedTypeReferencesRule = createRule<[], MessageIds>({
const fixes = new FixList();
fixes.addFixes(fixer.replaceText(node.expression, newTypeName));
const program = getProgram(node);
if (program !== undefined) {
if (program !== undefined && !fixedImportNames.includes(deprecatedTypeName)) {
fixes.addFixes(
replaceImportInFile(
program,
Expand All @@ -317,6 +321,7 @@ export const noDeprecatedTypeReferencesRule = createRule<[], MessageIds>({
newTypeToPackageName[newTypeName],
)(fixer),
);
fixedImportNames.push(deprecatedTypeName);
}
return fixes.getFixes();
},
Expand All @@ -325,6 +330,7 @@ export const noDeprecatedTypeReferencesRule = createRule<[], MessageIds>({
}
},

// lint syntax like `interface MyInterface extends Blueprint.DeprecatedInterface {...}`
"TSInterfaceHeritage MemberExpression": (node: TSESTree.MemberExpression) => {
if (
node.property.type !== TSESTree.AST_NODE_TYPES.Identifier ||
Expand Down
23 changes: 0 additions & 23 deletions packages/eslint-plugin/test/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ ruleTester.run("no-deprecated-type-references", noDeprecatedTypeReferencesRule,
};
`,
},
// N.B. it is unreliable/impossible to test multiple fixes with ESLint's RuleTester, so we test those separately

// N.B. it is difficult to test fixes of multiple violations with ESLint's RuleTester, so we cannot have a test
// case with both `ISelectProps` and `ITimezoneItem`.
// see https://github.com/eslint/eslint/issues/11187#issuecomment-470990425
{
code: dedent`
Expand Down Expand Up @@ -138,6 +140,66 @@ ruleTester.run("no-deprecated-type-references", noDeprecatedTypeReferencesRule,
const mySelectProps: SelectProps = { items: [] };
`,
},

// Ensure that multiple references/uses of the _same_ deprecated type are all fixed
{
code: dedent`
import { ItemRenderer, IItemRendererProps } from "@blueprintjs/select";
const fooRenderer: ItemRenderer<any> = (item: any, props: IItemRendererProps) => {
return "foo";
}
const barRenderer: ItemRenderer<any> = (item: any, props: IItemRendererProps) => {
return "bar";
}
`,
errors: [
{
messageId: "migration",
data: { deprecatedTypeName: "IItemRendererProps", newTypeName: "ItemRendererProps" },
},
{
messageId: "migration",
data: { deprecatedTypeName: "IItemRendererProps", newTypeName: "ItemRendererProps" },
},
],
output: dedent`
import { ItemRenderer, ItemRendererProps } from "@blueprintjs/select";
const fooRenderer: ItemRenderer<any> = (item: any, props: ItemRendererProps) => {
return "foo";
}
const barRenderer: ItemRenderer<any> = (item: any, props: ItemRendererProps) => {
return "bar";
}
`,
},
{
code: dedent`
import { Button, IButtonProps } from "@blueprintjs/core";
const ButtonAlias = (props: IButtonProps) => <Button {...props} />;
interface MyButtonProps extends IButtonProps {
type: string;
}
const MyButton = (props: MyButtonProps) => <Button {...props} />;
`,
errors: [
{
messageId: "migration",
data: { deprecatedTypeName: "IButtonProps", newTypeName: "ButtonProps" },
},
{
messageId: "migration",
data: { deprecatedTypeName: "IButtonProps", newTypeName: "ButtonProps" },
},
],
output: dedent`
import { Button, ButtonProps } from "@blueprintjs/core";
const ButtonAlias = (props: ButtonProps) => <Button {...props} />;
interface MyButtonProps extends ButtonProps {
type: string;
}
const MyButton = (props: MyButtonProps) => <Button {...props} />;
`,
},
],
valid: [
{
Expand Down

1 comment on commit 8ff2797

@blueprint-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix(no-deprecated-type-references): no overlapping import fixes (#5530)

Previews: documentation | landing | table | demo

Please sign in to comment.