Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lint rules: Add prefer-flex rule w/autofix #1628

Merged
merged 18 commits into from
Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Box as GestaltBox, Flex as RenamedFlex } from 'gestalt';

export default function TestElement() {
return (
<RenamedFlex>
<GestaltBox marginBottom={3} rounding={2} />
<GestaltBox display="flex" alignItems="center" />
</RenamedFlex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Box as GestaltBox, Flex as RenamedFlex } from 'gestalt';

export default function TestElement() {
return (
<RenamedFlex>
<GestaltBox marginBottom={3} rounding={2} />
<RenamedFlex alignItems="center" justifyContent="start" />
</RenamedFlex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Box as GestaltBox, Flex } from 'gestalt';

export default function TestElement() {
return (
<Flex>
<GestaltBox marginBottom={3} rounding={2} />
<GestaltBox display="flex" alignItems="center" />
</Flex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Box as GestaltBox, Flex } from 'gestalt';

export default function TestElement() {
return (
<Flex>
<GestaltBox marginBottom={3} rounding={2} />
<Flex alignItems="center" justifyContent="start" />
</Flex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Box, Flex as GestaltFlex } from 'gestalt';

export default function TestElement() {
return (
<GestaltFlex>
<Box marginBottom={3} rounding={2} />
<Box display="flex" alignItems="center" />
</GestaltFlex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Box, Flex as GestaltFlex } from 'gestalt';

export default function TestElement() {
return (
<GestaltFlex>
<Box marginBottom={3} rounding={2} />
<GestaltFlex alignItems="center" justifyContent="start" />
</GestaltFlex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Box, Flex } from 'gestalt';

export default function TestElement() {
return (
<Flex>
<Box marginBottom={3} rounding={2} />
<Box display="flex" alignItems="center" />
</Flex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Box, Flex } from 'gestalt';

export default function TestElement() {
return (
<Flex>
<Box marginBottom={3} rounding={2} />
<Flex alignItems="center" justifyContent="start" />
</Flex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Fragment } from 'react';
import { Box as GestaltBox } from 'gestalt';

export default function TestElement() {
return (
<Fragment>
<GestaltBox marginBottom={3} rounding={2} />
<GestaltBox display="flex" alignItems="center" />
</Fragment>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Fragment } from 'react';
import { Box as GestaltBox, Flex as GestaltFlex } from 'gestalt';

export default function TestElement() {
return (
<Fragment>
<GestaltBox marginBottom={3} rounding={2} />
<GestaltFlex alignItems="center" justifyContent="start" />
</Fragment>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Fragment } from 'react';
import { Box } from 'gestalt';

export default function TestElement() {
return (
<Fragment>
<Box marginBottom={3} rounding={2} />
<Box display="flex" alignItems="center" />
</Fragment>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Fragment } from 'react';
import { Box, Flex } from 'gestalt';

export default function TestElement() {
return (
<Fragment>
<Box marginBottom={3} rounding={2} />
<Flex alignItems="center" justifyContent="start" />
</Fragment>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Box } from 'gestalt';

export default function TestElement() {
return <Box display="flex" alignItems="center" />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Flex } from 'gestalt';

export default function TestElement() {
return <Flex alignItems="center" justifyContent="start" />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Box } from 'gestalt';

export default function TestElement() {
return <Box display="flex" padding={2} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Box } from 'gestalt';

export default function TestElement() {
return <Box rounding={2} />;
}
41 changes: 23 additions & 18 deletions packages/eslint-plugin-gestalt/src/eslintASTFixers.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ type GenericNode = {| [string]: any |};
Fixers are the functions executed in the fix method inside context.report
*/

type InsertGestaltImportTopFileFixerType = ({|
context: GenericNode,
type updateGestaltImportFixerType = ({|
fixer: GenericNode,
gestaltImportNode: GenericNode,
importsToRemove?: $ReadOnlyArray<string>,
newComponentName: string,
programNode: GenericNode,
|}) => GenericNode;

/** This function updates the imports to include the new Gestalt component if needed. If there's no previous Gestalt import, it's preprended at the top of the file. It mantains aliased imports.
*/
export const updateGestaltImportFixer: InsertGestaltImportTopFileFixerType = ({
export const updateGestaltImportFixer: updateGestaltImportFixerType = ({
fixer,
gestaltImportNode,
importsToRemove,
newComponentName,
programNode,
}) => {
Expand All @@ -45,7 +46,11 @@ export const updateGestaltImportFixer: InsertGestaltImportTopFileFixerType = ({
importsComponentsArray.push([newComponentName, newComponentName]);
}

const sortedImports = importsComponentsArray
const filteredImportComponents = importsToRemove
? importsComponentsArray.filter((component) => !importsToRemove.includes(component[0]))
: importsComponentsArray;

const sortedImports = filteredImportComponents
.map((cmp) => {
if (cmp[0] === cmp[1]) return cmp[0]; // import and local names match
return `${cmp[0]} as ${cmp[1]}`; // import and local names don't match, keep alias
Expand Down Expand Up @@ -81,8 +86,8 @@ export const renameTagFixer: RenameTagFixerType = ({
}) => {
return [elementNode.openingElement, elementNode.closingElement]
.map((node) => {
// $FlowFixMe[incompatible-type] Flow is not detecting the method filter(Boolean)
if (!node) return false;
if (!node) return undefined;

const namedImportsComponents =
getNamedImportsComponents({
importNode: gestaltImportNode,
Expand Down Expand Up @@ -125,19 +130,19 @@ export const renameTagWithPropsFixer: RenameTagWithPropsFixerType = ({
newComponentName,
tagName,
}) => {
return [elementNode.openingElement, elementNode.closingElement]
const openingElement =
elementNode.type === 'JSXOpeningElement' ? elementNode : elementNode.openingElement;
const finalNewComponentName = getLocalComponentImportName({
importNode: gestaltImportNode,
componentName: newComponentName,
});
const completeOpeningNode = `<${finalNewComponentName} ${modifiedPropsString}${
elementNode.closingElement ? '' : ' /'
}>`;

return [openingElement, elementNode.closingElement]
.map((node, index) => {
// $FlowFixMe[incompatible-type] Flow is not detecting the method filter(Boolean)
if (!node) return false;

const finalNewComponentName = getLocalComponentImportName({
importNode: gestaltImportNode,
componentName: newComponentName,
});

const completeOpeningNode = `<${finalNewComponentName} ${modifiedPropsString}${
elementNode.closingElement ? '' : ' /'
}>`;
if (!node) return undefined;

return index === 0
? fixer.replaceText(node, completeOpeningNode)
Expand Down
9 changes: 6 additions & 3 deletions packages/eslint-plugin-gestalt/src/eslintASTHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ const buildProps: RetrieveKeyValuesFromPropsType = ({
const openingElement =
elementNode.type === 'JSXOpeningElement' ? elementNode : elementNode.openingElement;

if (elementNode.openingElement.attributes.length === 0) return propsToAdd ?? '';
if (openingElement.attributes.length === 0) {
return propsToAdd ?? '';
}

const filteredProps = propsToRemove
? openingElement.attributes.filter((prop) => !(propsToRemove ?? []).includes(prop.name.name))
: openingElement.attributes;
Expand Down Expand Up @@ -315,9 +318,9 @@ type GetLocalComponentImportNameType = ({|

/** This function returns the local component name, returning the alias.
Example 1:
import { Box } from 'gestalt ?? returns Box
import { Box } from 'gestalt // returns Box
Example 2:
import { Box as RenamedBox } from 'gestalt ?? returns RenamedBox
import { Box as RenamedBox } from 'gestalt // returns RenamedBox
*/
const getLocalComponentImportName: GetLocalComponentImportNameType = ({
importNode,
Expand Down
1 change: 0 additions & 1 deletion packages/eslint-plugin-gestalt/src/prefer-box-as-tag.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ const rule: ESLintRule = {
});

const importFixers = updateGestaltImportFixer({
context,
fixer,
gestaltImportNode,
newComponentName: 'Box',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ const rule: ESLintRule = {
});

const importFixers = updateGestaltImportFixer({
context,
gestaltImportNode,
fixer,
newComponentName: 'Box',
Expand Down Expand Up @@ -151,7 +150,6 @@ const rule: ESLintRule = {
});

const importFixers = updateGestaltImportFixer({
context,
gestaltImportNode,
fixer,
newComponentName: 'Box',
Expand Down