eslint-plugin-nextfriday 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # eslint-plugin-nextfriday
2
2
 
3
+ ## 1.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#26](https://github.com/next-friday/eslint-plugin-nextfriday/pull/26) [`e90935a`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/e90935a56129ff84efc9df5de3f43e8e4a61af16) Thanks [@nextfridaydeveloper](https://github.com/nextfridaydeveloper)! - Add two new rules to improve code readability and debugging: `no-complex-inline-return` disallows complex inline expressions (such as ternary operators, logical expressions, or `new` expressions) directly in return statements, requiring extraction to a `const` variable instead; and `no-logic-in-params` prohibits using logic or conditions (e.g., ternary, logical, comparison, or negation operators) within function parameters, enforcing the use of intermediate `const` variables to enhance clarity and allow inspection of values.
8
+
3
9
  ## 1.3.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -67,6 +67,8 @@ export default [
67
67
  "nextfriday/prefer-import-type": "error",
68
68
  "nextfriday/prefer-named-param-types": "error",
69
69
  "nextfriday/prefer-react-import-types": "error",
70
+ "nextfriday/no-complex-inline-return": "error",
71
+ "nextfriday/no-logic-in-params": "error",
70
72
  "nextfriday/jsx-pascal-case": "error",
71
73
  "nextfriday/prefer-interface-over-inline-types": "error",
72
74
  "nextfriday/react-props-destructure": "error",
@@ -107,20 +109,22 @@ module.exports = {
107
109
 
108
110
  ## Rules
109
111
 
110
- | Rule | Description | Fixable |
111
- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------- |
112
- | [no-emoji](docs/rules/NO_EMOJI.md) | Disallow emojis in code | ❌ |
113
- | [file-kebab-case](docs/rules/FILE_KEBAB_CASE.md) | Enforce kebab-case filenames for .ts and .js files | ❌ |
114
- | [jsx-pascal-case](docs/rules/JSX_PASCAL_CASE.md) | Enforce PascalCase filenames for .jsx and .tsx files | ❌ |
115
- | [md-filename-case-restriction](docs/rules/MD_FILENAME_CASE_RESTRICTION.md) | Enforce SNAKE_CASE filenames for .md files | ❌ |
116
- | [prefer-destructuring-params](docs/rules/PREFER_DESTRUCTURING_PARAMS.md) | Enforce destructuring for functions with multiple parameters | ❌ |
117
- | [no-explicit-return-type](docs/rules/NO_EXPLICIT_RETURN_TYPE.md) | Disallow explicit return types on functions | ✅ |
118
- | [prefer-import-type](docs/rules/PREFER_IMPORT_TYPE.md) | Enforce using 'import type' for type-only imports | ✅ |
119
- | [prefer-named-param-types](docs/rules/PREFER_NAMED_PARAM_TYPES.md) | Enforce named types for function parameters with object types | ❌ |
120
- | [prefer-interface-over-inline-types](docs/rules/PREFER_INTERFACE_OVER_INLINE_TYPES.md) | Enforce interface declarations over inline types for React props | ❌ |
121
- | [prefer-react-import-types](docs/rules/PREFER_REACT_IMPORT_TYPES.md) | Enforce direct imports from 'react' instead of React.X | ✅ |
122
- | [react-props-destructure](docs/rules/REACT_PROPS_DESTRUCTURE.md) | Enforce destructuring props inside React component body | ❌ |
123
- | [enforce-readonly-component-props](docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md) | Enforce Readonly wrapper for React component props | ✅ |
112
+ | Rule | Description | Fixable |
113
+ | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------- |
114
+ | [no-emoji](docs/rules/NO_EMOJI.md) | Disallow emojis in code | ❌ |
115
+ | [file-kebab-case](docs/rules/FILE_KEBAB_CASE.md) | Enforce kebab-case filenames for .ts and .js files | ❌ |
116
+ | [jsx-pascal-case](docs/rules/JSX_PASCAL_CASE.md) | Enforce PascalCase filenames for .jsx and .tsx files | ❌ |
117
+ | [md-filename-case-restriction](docs/rules/MD_FILENAME_CASE_RESTRICTION.md) | Enforce SNAKE_CASE filenames for .md files | ❌ |
118
+ | [prefer-destructuring-params](docs/rules/PREFER_DESTRUCTURING_PARAMS.md) | Enforce destructuring for functions with multiple parameters | ❌ |
119
+ | [no-explicit-return-type](docs/rules/NO_EXPLICIT_RETURN_TYPE.md) | Disallow explicit return types on functions | ✅ |
120
+ | [prefer-import-type](docs/rules/PREFER_IMPORT_TYPE.md) | Enforce using 'import type' for type-only imports | ✅ |
121
+ | [prefer-named-param-types](docs/rules/PREFER_NAMED_PARAM_TYPES.md) | Enforce named types for function parameters with object types | ❌ |
122
+ | [prefer-interface-over-inline-types](docs/rules/PREFER_INTERFACE_OVER_INLINE_TYPES.md) | Enforce interface declarations over inline types for React props | ❌ |
123
+ | [prefer-react-import-types](docs/rules/PREFER_REACT_IMPORT_TYPES.md) | Enforce direct imports from 'react' instead of React.X | ✅ |
124
+ | [react-props-destructure](docs/rules/REACT_PROPS_DESTRUCTURE.md) | Enforce destructuring props inside React component body | ❌ |
125
+ | [enforce-readonly-component-props](docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md) | Enforce Readonly wrapper for React component props | ✅ |
126
+ | [no-complex-inline-return](docs/rules/NO_COMPLEX_INLINE_RETURN.md) | Disallow complex inline expressions in return statements - prefer const first | ❌ |
127
+ | [no-logic-in-params](docs/rules/NO_LOGIC_IN_PARAMS.md) | Disallow logic or conditions in function parameters - extract to const first | ❌ |
124
128
 
125
129
  ## Configurations
126
130
 
@@ -138,6 +142,8 @@ Basic configuration without JSX-specific rules:
138
142
  - `nextfriday/prefer-import-type`: `"error"`
139
143
  - `nextfriday/prefer-named-param-types`: `"error"`
140
144
  - `nextfriday/prefer-react-import-types`: `"error"`
145
+ - `nextfriday/no-complex-inline-return`: `"error"`
146
+ - `nextfriday/no-logic-in-params`: `"error"`
141
147
 
142
148
  #### `base/recommended`
143
149
 
@@ -0,0 +1,136 @@
1
+ # no-complex-inline-return
2
+
3
+ Disallow complex inline expressions in return statements - prefer extracting to a const first.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces a pattern where complex expressions (ternary operators, logical expressions, new expressions) are extracted to a const variable before being returned. This improves code readability and makes debugging easier by allowing you to inspect intermediate values.
8
+
9
+ **Incorrect** code for this rule:
10
+
11
+ ```typescript
12
+ function waitForLoad(targetWindow: Window) {
13
+ return targetWindow.document.readyState === "complete"
14
+ ? Promise.resolve()
15
+ : new Promise<void>((resolve) => {
16
+ targetWindow.addEventListener(
17
+ "load",
18
+ () => {
19
+ resolve();
20
+ },
21
+ {
22
+ once: true,
23
+ },
24
+ );
25
+ });
26
+ }
27
+
28
+ function getValue(condition: boolean) {
29
+ return condition ? "yes" : "no";
30
+ }
31
+
32
+ function getUser(user: User | null) {
33
+ return user || defaultUser;
34
+ }
35
+
36
+ function createInstance() {
37
+ return new MyClass();
38
+ }
39
+
40
+ function checkStatus(a: boolean, b: boolean) {
41
+ return a && b;
42
+ }
43
+ ```
44
+
45
+ **Correct** code for this rule:
46
+
47
+ ```typescript
48
+ function waitForLoad(targetWindow: Window) {
49
+ const loadPromise =
50
+ targetWindow.document.readyState === "complete"
51
+ ? Promise.resolve()
52
+ : new Promise<void>((resolve) => {
53
+ targetWindow.addEventListener(
54
+ "load",
55
+ () => {
56
+ resolve();
57
+ },
58
+ {
59
+ once: true,
60
+ },
61
+ );
62
+ });
63
+
64
+ return loadPromise;
65
+ }
66
+
67
+ function getValue(condition: boolean) {
68
+ const value = condition ? "yes" : "no";
69
+ return value;
70
+ }
71
+
72
+ function getUser(user: User | null) {
73
+ const activeUser = user || defaultUser;
74
+ return activeUser;
75
+ }
76
+
77
+ function createInstance() {
78
+ const instance = new MyClass();
79
+ return instance;
80
+ }
81
+
82
+ function checkStatus(a: boolean, b: boolean) {
83
+ const isValid = a && b;
84
+ return isValid;
85
+ }
86
+
87
+ // Simple returns are still allowed
88
+ function getName() {
89
+ return "John Doe";
90
+ }
91
+
92
+ function getAge() {
93
+ return 42;
94
+ }
95
+
96
+ function callFunction() {
97
+ return someFunction();
98
+ }
99
+
100
+ function getMath() {
101
+ return a + b;
102
+ }
103
+ ```
104
+
105
+ ## Benefits
106
+
107
+ - **Better readability**: Complex logic is separated from the return statement
108
+ - **Easier debugging**: Intermediate values can be inspected in debuggers
109
+ - **Self-documenting**: Variable names can describe what the complex expression represents
110
+ - **Consistent style**: Enforces a uniform approach to handling complex return values
111
+
112
+ ## When Not To Use
113
+
114
+ - For very simple projects where inline expressions are preferred
115
+ - When you prefer a more compact coding style
116
+ - In cases where the expression is trivial and doesn't benefit from extraction
117
+
118
+ ## What This Rule Checks
119
+
120
+ This rule flags the following patterns when used directly in return statements:
121
+
122
+ - **Ternary expressions** (conditional operators): `condition ? value1 : value2`
123
+ - **Logical expressions**: `a && b`, `a || b`, `a ?? b`
124
+ - **New expressions**: `new MyClass()`
125
+
126
+ The following are allowed in return statements:
127
+
128
+ - Simple values (literals, variables)
129
+ - Function calls
130
+ - Binary expressions (math operations like `a + b`)
131
+ - Object/array literals
132
+ - Member expressions (`obj.prop`)
133
+
134
+ ## Related Rules
135
+
136
+ - No related rules
@@ -0,0 +1,122 @@
1
+ # no-logic-in-params
2
+
3
+ Disallow logic or conditions in function parameters - extract to a const variable first.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces a pattern where complex expressions (logical operators, ternary operators, comparison operators) are extracted to a const variable before being passed as function arguments. This improves code readability, makes debugging easier, and helps maintain cleaner function calls.
8
+
9
+ **Incorrect** code for this rule:
10
+
11
+ ```typescript
12
+ // Nullish coalescing
13
+ functionFoo(bar ?? baz);
14
+
15
+ // Ternary operator
16
+ handleUser(isActive ? activeUser : inactiveUser);
17
+
18
+ // Logical AND
19
+ processData(hasPermission && isValid);
20
+
21
+ // Logical OR
22
+ setConfig(customConfig || defaultConfig);
23
+
24
+ // Comparison operators
25
+ validateInput(value > 100);
26
+ checkEquality(a === b);
27
+
28
+ // Negation
29
+ toggleFeature(!isEnabled);
30
+
31
+ // Multiple parameters with logic
32
+ createUser(username, age >= 18, status === "active");
33
+
34
+ // New expression with logic
35
+ new MyClass(a || b);
36
+ ```
37
+
38
+ **Correct** code for this rule:
39
+
40
+ ```typescript
41
+ // Extract logic to a variable first
42
+ const value = bar ?? baz;
43
+ functionFoo(value);
44
+
45
+ const user = isActive ? activeUser : inactiveUser;
46
+ handleUser(user);
47
+
48
+ const canProcess = hasPermission && isValid;
49
+ processData(canProcess);
50
+
51
+ const config = customConfig || defaultConfig;
52
+ setConfig(config);
53
+
54
+ const isValid = value > 100;
55
+ validateInput(isValid);
56
+
57
+ const areEqual = a === b;
58
+ checkEquality(areEqual);
59
+
60
+ const shouldDisable = !isEnabled;
61
+ toggleFeature(shouldDisable);
62
+
63
+ const isAdult = age >= 18;
64
+ const isActive = status === "active";
65
+ createUser(username, isAdult, isActive);
66
+
67
+ const param = a || b;
68
+ new MyClass(param);
69
+
70
+ // Simple values are still allowed
71
+ functionFoo(bar);
72
+ functionFoo(42);
73
+ functionFoo("string");
74
+ functionFoo(obj.property);
75
+ functionFoo(getValue());
76
+
77
+ // Arithmetic operations are allowed
78
+ calculate(a + b);
79
+ multiply(x * y);
80
+
81
+ // Object/array literals are allowed
82
+ configure({ key: "value" });
83
+ process([1, 2, 3]);
84
+ ```
85
+
86
+ ## Benefits
87
+
88
+ - **Better readability**: Logic is separated from function calls, making code easier to scan
89
+ - **Easier debugging**: Intermediate values can be inspected in debuggers before being passed to functions
90
+ - **Self-documenting**: Variable names describe what the complex expression represents
91
+ - **Consistent style**: Enforces a uniform approach to handling complex function arguments
92
+ - **Reduced cognitive load**: Readers don't need to mentally evaluate expressions while also understanding function calls
93
+
94
+ ## When Not To Use
95
+
96
+ - For very simple projects where inline expressions are preferred
97
+ - When you prefer a more compact coding style
98
+ - In cases where the expression is trivial and doesn't benefit from extraction
99
+
100
+ ## What This Rule Checks
101
+
102
+ This rule flags the following patterns when used as function arguments:
103
+
104
+ - **Ternary expressions** (conditional operators): `condition ? value1 : value2`
105
+ - **Logical expressions**: `a && b`, `a || b`, `a ?? b`
106
+ - **Comparison operators**: `===`, `!==`, `==`, `!=`, `>`, `<`, `>=`, `<=`
107
+ - **Type checking operators**: `in`, `instanceof`
108
+ - **Negation operator**: `!value`
109
+
110
+ The following are allowed as function arguments:
111
+
112
+ - Simple values (literals, variables)
113
+ - Function calls
114
+ - Member expressions (`obj.prop`)
115
+ - Arithmetic operations (`a + b`, `a * b`, etc.)
116
+ - Object/array literals
117
+ - Template literals
118
+ - Spread operators (`...args`)
119
+
120
+ ## Related Rules
121
+
122
+ - [no-complex-inline-return](./NO_COMPLEX_INLINE_RETURN.md) - Similar rule but for return statements