diff options
Diffstat (limited to 'eslint')
-rw-r--r-- | eslint/__tests__/avoid-unwrapped-text.test.js | 65 | ||||
-rw-r--r-- | eslint/avoid-unwrapped-text.js | 38 |
2 files changed, 102 insertions, 1 deletions
diff --git a/eslint/__tests__/avoid-unwrapped-text.test.js b/eslint/__tests__/avoid-unwrapped-text.test.js index 0fbc01123..7c667b4a8 100644 --- a/eslint/__tests__/avoid-unwrapped-text.test.js +++ b/eslint/__tests__/avoid-unwrapped-text.test.js @@ -246,6 +246,41 @@ describe('avoid-unwrapped-text', () => { </Foo> `, }, + + { + code: ` +function Stuff() { + return <Text>foo</Text> +} + `, + }, + + { + code: ` +function Stuff({ foo }) { + return <View>{foo}</View> +} + `, + }, + + { + code: ` +function MyText() { + return <Text>foo</Text> +} + `, + }, + + { + code: ` +function MyText({ foo }) { + if (foo) { + return <Text>foo</Text> + } + return <Text>foo</Text> +} + `, + }, ], invalid: [ @@ -390,6 +425,36 @@ describe('avoid-unwrapped-text', () => { `, errors: 1, }, + + { + code: ` +function MyText() { + return <Foo /> +} + `, + errors: 1, + }, + + { + code: ` +function MyText({ foo }) { + return <Foo>{foo}</Foo> +} + `, + errors: 1, + }, + + { + code: ` +function MyText({ foo }) { + if (foo) { + return <Foo>{foo}</Foo> + } + return <Text>foo</Text> +} + `, + errors: 1, + }, ], } diff --git a/eslint/avoid-unwrapped-text.js b/eslint/avoid-unwrapped-text.js index c9e72386e..79d099f00 100644 --- a/eslint/avoid-unwrapped-text.js +++ b/eslint/avoid-unwrapped-text.js @@ -35,6 +35,11 @@ exports.create = function create(context) { const impliedTextComponents = options.impliedTextComponents ?? [] const textProps = [...impliedTextProps] const textComponents = ['Text', ...impliedTextComponents] + + function isTextComponent(tagName) { + return textComponents.includes(tagName) || tagName.endsWith('Text') + } + return { JSXText(node) { if (typeof node.value !== 'string' || hasOnlyLineBreak(node.value)) { @@ -44,7 +49,7 @@ exports.create = function create(context) { while (parent) { if (parent.type === 'JSXElement') { const tagName = getTagName(parent) - if (textComponents.includes(tagName) || tagName.endsWith('Text')) { + if (isTextComponent(tagName)) { // We're good. return } @@ -107,5 +112,36 @@ exports.create = function create(context) { continue } }, + ReturnStatement(node) { + let fnScope = context.getScope() + while (fnScope && fnScope.type !== 'function') { + fnScope = fnScope.upper + } + if (!fnScope) { + return + } + const fn = fnScope.block + if (!fn.id || fn.id.type !== 'Identifier' || !fn.id.name) { + return + } + if (!/^[A-Z]\w*Text$/.test(fn.id.name)) { + return + } + if (!node.argument || node.argument.type !== 'JSXElement') { + return + } + const openingEl = node.argument.openingElement + if (openingEl.name.type !== 'JSXIdentifier') { + return + } + const returnedComponentName = openingEl.name.name + if (!isTextComponent(returnedComponentName)) { + context.report({ + node, + message: + 'Components ending with *Text must return <Text> or <SomeText>.', + }) + } + }, } } |