UNPKG

2.86 kBJavaScriptView Raw
1/**
2 * @fileoverview Enforce ES5 or ES6 class for returning value in render function.
3 * @author Mark Orel
4 */
5
6'use strict';
7
8const Components = require('../util/Components');
9const astUtil = require('../util/ast');
10const docsUrl = require('../util/docsUrl');
11
12// ------------------------------------------------------------------------------
13// Rule Definition
14// ------------------------------------------------------------------------------
15
16module.exports = {
17 meta: {
18 docs: {
19 description: 'Enforce ES5 or ES6 class for returning value in render function',
20 category: 'Possible Errors',
21 recommended: true,
22 url: docsUrl('require-render-return')
23 },
24 schema: [{}]
25 },
26
27 create: Components.detect((context, components, utils) => {
28 /**
29 * Mark a return statement as present
30 * @param {ASTNode} node The AST node being checked.
31 */
32 function markReturnStatementPresent(node) {
33 components.set(node, {
34 hasReturnStatement: true
35 });
36 }
37
38 /**
39 * Find render method in a given AST node
40 * @param {ASTNode} node The component to find render method.
41 * @returns {ASTNode} Method node if found, undefined if not.
42 */
43 function findRenderMethod(node) {
44 const properties = astUtil.getComponentProperties(node);
45 return properties
46 .filter((property) => astUtil.getPropertyName(property) === 'render' && property.value)
47 .find((property) => astUtil.isFunctionLikeExpression(property.value));
48 }
49
50 return {
51 ReturnStatement(node) {
52 const ancestors = context.getAncestors(node).reverse();
53 let depth = 0;
54 ancestors.forEach((ancestor) => {
55 if (/Function(Expression|Declaration)$/.test(ancestor.type)) {
56 depth++;
57 }
58 if (
59 /(MethodDefinition|(Class)?Property)$/.test(ancestor.type)
60 && astUtil.getPropertyName(ancestor) === 'render'
61 && depth <= 1
62 ) {
63 markReturnStatementPresent(node);
64 }
65 });
66 },
67
68 ArrowFunctionExpression(node) {
69 if (node.expression === false || astUtil.getPropertyName(node.parent) !== 'render') {
70 return;
71 }
72 markReturnStatementPresent(node);
73 },
74
75 'Program:exit'() {
76 const list = components.list();
77 Object.keys(list).forEach((component) => {
78 if (
79 !findRenderMethod(list[component].node)
80 || list[component].hasReturnStatement
81 || (!utils.isES5Component(list[component].node) && !utils.isES6Component(list[component].node))
82 ) {
83 return;
84 }
85 context.report({
86 node: findRenderMethod(list[component].node),
87 message: 'Your render method should have a return statement'
88 });
89 });
90 }
91 };
92 })
93};