Skip to content

Commit

Permalink
fix(EmptyState): components no longer exported
Browse files Browse the repository at this point in the history
  • Loading branch information
thatblindgeye committed May 20, 2024
1 parent b242349 commit 89a1a81
Show file tree
Hide file tree
Showing 5 changed files with 263 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
### emptyState-nonExported-components [(#10364)](https://github.com/patternfly/patternfly-react/pull/10364)

EmptyStateHeader and EmptyStateIcon are no longer exported by PatternFly. This rule will only apply fixes for exports of these components, as our rule for unused imports will handle applying fixes for imports.

#### Examples

In:

```jsx
%inputExample%
```

Out:

```jsx
%outputExample%
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
const ruleTester = require("../../ruletester");
import * as rule from "./emptyState-nonExported-components";

ruleTester.run("emptyState-nonExported-components", rule, {
valid: [
{
code: `import { EmptyStateHeader } from '@some/other/package';`,
},
{
code: `import { EmptyStateIcon } from '@some/other/package';`,
},
],
invalid: [
{
code: `import { EmptyStateHeader } from '@patternfly/react-core';`,
output: `import { EmptyStateHeader } from '@patternfly/react-core';`,
errors: [
{
message: `EmptyStateHeader is no longer exported by PatternFly. This rule will not fix any imports, as our cleanup rule handles removal of unused imports.`,
type: "ImportSpecifier",
},
],
},
{
code: `import { EmptyStateHeader as CustomHeader } from '@patternfly/react-core';`,
output: `import { EmptyStateHeader as CustomHeader } from '@patternfly/react-core';`,
errors: [
{
message: `EmptyStateHeader is no longer exported by PatternFly. This rule will not fix any imports, as our cleanup rule handles removal of unused imports.`,
type: "ImportSpecifier",
},
],
},
{
code: `export { EmptyStateHeader } from '@patternfly/react-core';`,
output: ``,
errors: [
{
message: `EmptyStateHeader is no longer exported by PatternFly.`,
type: "ExportNamedDeclaration",
},
],
},
{
code: `export { EmptyStateHeader as CustomHeader } from '@patternfly/react-core';`,
output: ``,
errors: [
{
message: `EmptyStateHeader is no longer exported by PatternFly.`,
type: "ExportNamedDeclaration",
},
],
},
{
code: `export { EmptyStateHeader, EmptyStateIcon } from '@patternfly/react-core';`,
output: ``,
errors: [
{
message: `EmptyStateHeader and EmptyStateIcon are no longer exported by PatternFly.`,
type: "ExportNamedDeclaration",
},
],
},
{
code: `export { EmptyStateHeader, Button, EmptyStateIcon } from '@patternfly/react-core';`,
output: `export { Button } from '@patternfly/react-core';`,
errors: [
{
message: `EmptyStateHeader is no longer exported by PatternFly.`,
type: "ExportNamedDeclaration",
},
{
message: `EmptyStateIcon is no longer exported by PatternFly.`,
type: "ExportNamedDeclaration",
},
],
},
{
code: `import { EmptyStateHeader } from '@patternfly/react-core';export { EmptyStateHeader };`,
output: `import { EmptyStateHeader } from '@patternfly/react-core';`,
errors: [
{
message: `EmptyStateHeader is no longer exported by PatternFly. This rule will not fix any imports, as our cleanup rule handles removal of unused imports.`,
type: "ImportSpecifier",
},
{
message: `EmptyStateHeader is no longer exported by PatternFly.`,
type: "ExportNamedDeclaration",
},
],
},
{
code: `import { EmptyStateHeader as CustomHeader } from '@patternfly/react-core';export { CustomHeader };`,
output: `import { EmptyStateHeader as CustomHeader } from '@patternfly/react-core';`,
errors: [
{
message: `EmptyStateHeader is no longer exported by PatternFly. This rule will not fix any imports, as our cleanup rule handles removal of unused imports.`,
type: "ImportSpecifier",
},
{
message: `CustomHeader is no longer exported by PatternFly.`,
type: "ExportNamedDeclaration",
},
],
},
{
code: `import { EmptyStateHeader } from '@patternfly/react-core';export { EmptyStateHeader as CustomHeader };`,
output: `import { EmptyStateHeader } from '@patternfly/react-core';`,
errors: [
{
message: `EmptyStateHeader is no longer exported by PatternFly. This rule will not fix any imports, as our cleanup rule handles removal of unused imports.`,
type: "ImportSpecifier",
},
{
message: `EmptyStateHeader is no longer exported by PatternFly.`,
type: "ExportNamedDeclaration",
},
],
},
],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { Rule } from "eslint";
import {
ImportSpecifier,
ExportSpecifier,
ExportNamedDeclaration,
ExportDefaultDeclaration,
} from "estree-jsx";
import { getFromPackage } from "../../helpers";

// https://github.com/patternfly/patternfly-react/pull/10364
module.exports = {
meta: { fixable: "code" },
create: function (context: Rule.RuleContext) {
const { imports, exports } = getFromPackage(
context,
"@patternfly/react-core"
);
const emptyStateComponents = ["EmptyStateHeader", "EmptyStateIcon"];
const emptyStateImports = imports.filter((specifier) =>
emptyStateComponents.includes(specifier.imported.name)
);
const emptyStateExports = exports.filter((specifier) =>
emptyStateComponents.includes(specifier.local.name)
);

if (!emptyStateImports.length && !emptyStateExports.length) {
return {};
}

return {
ImportSpecifier(node: ImportSpecifier) {
if (!emptyStateImports.length) {
return;
}

emptyStateImports.forEach((esImport) => {
context.report({
node,
message: `${esImport.imported.name} is no longer exported by PatternFly. This rule will not fix any imports, as our cleanup rule handles removal of unused imports.`,
});
});
},
ExportNamedDeclaration(node: ExportNamedDeclaration) {
const exportsToRemove = node.specifiers.filter(
(spec) =>
(emptyStateComponents.includes(spec.local.name) &&
node.source?.value === "@patternfly/react-core") ||
emptyStateImports.some((imp) => imp.local.name === spec.local.name)
);
if (!exportsToRemove.length) {
return;
}

if (exportsToRemove.length === node.specifiers.length) {
const validExportNames = exportsToRemove
.map((exportToRemove) => exportToRemove.local.name)
.join(" and ");
context.report({
node,
message: `${validExportNames} ${
exportsToRemove.length > 1 ? "are" : "is"
} no longer exported by PatternFly.`,
fix(fixer) {
return fixer.remove(node);
},
});

return;
}

exportsToRemove.forEach((exportToRemove) => {
const { range } = exportToRemove;
const tokenBefore = context
.getSourceCode()
.getTokenBefore(exportToRemove);
const isCommaBefore = tokenBefore?.value === ",";
const tokenAfter = context
.getSourceCode()
.getTokenAfter(exportToRemove);
const isCommaAfter = tokenAfter?.value === ",";
const rangeStartValue = isCommaBefore
? tokenBefore.range[0]
: range?.[0];
const rangeEndValue = isCommaAfter ? tokenAfter.range[1] : range?.[1];
context.report({
node,
message: `${exportToRemove.local.name} is no longer exported by PatternFly.`,
fix(fixer) {
return rangeStartValue && rangeEndValue
? fixer.removeRange([rangeStartValue, rangeEndValue])
: [];
},
});
});
},
ExportDefaultDeclaration(node: ExportDefaultDeclaration) {
const exportName =
node.declaration.type === "Identifier" && node.declaration.name;
const isEmptyStateDefaultExport = emptyStateImports.some(
(imp) =>
node.declaration.type === "Identifier" &&
imp.local.name === exportName
);

if (isEmptyStateDefaultExport) {
context.report({
node,
message: `${exportName} is no longer exported by PatternFly.`,
fix(fixer) {
return fixer.remove(node);
},
});
}
},
};
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { EmptyStateHeader, EmptyStateIcon } from "@patternfly/react-core";

export { EmptyStateHeader, EmptyStateIcon };
export {
EmptyStateHeader as CustomESHeader,
EmptyStateIcon as CustomESIcon,
} from "@patternfly/react-core";
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import { EmptyStateHeader, EmptyStateIcon } from "@patternfly/react-core";

0 comments on commit 89a1a81

Please sign in to comment.