Skip to content

fix(no-useless-undefined): Support functions with allowed undefined return types and mixed returns #2621

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 100 additions & 13 deletions rules/no-useless-undefined.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,89 @@
|| name === 'ref';
};

const getFunction = scope => {
for (; scope; scope = scope.upper) {
if (scope.type === 'function') {
return scope.block;
const getFunctionNode = (node) => {

Check failure on line 71 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Unexpected parentheses around single function argument
let current = node.parent;
while (current) {
if (
current.type === "FunctionDeclaration" ||

Check failure on line 75 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Strings must use singlequote

Check failure on line 75 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

'||' should be placed at the beginning of the line
current.type === "FunctionExpression" ||

Check failure on line 76 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Strings must use singlequote

Check failure on line 76 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

'||' should be placed at the beginning of the line
current.type === "ArrowFunctionExpression"

Check failure on line 77 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Strings must use singlequote
) {
return current;
}
if (current.type === "MethodDefinition") {

Check failure on line 81 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Expected blank line before this statement

Check failure on line 81 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Strings must use singlequote
return current.value;
}
current = current.parent;

Check failure on line 84 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Expected blank line before this statement
}
return null;

Check failure on line 86 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / run-rules-on-codebase

Use `undefined` instead of `null`

Check failure on line 86 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Expected blank line before this statement
};

const includesUndefined = (typeAnnotation) => {
if (!typeAnnotation) return false;
switch (typeAnnotation.type) {
case "TSUnionType":

Check failure on line 92 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / run-rules-on-codebase

Missing braces in case clause
return typeAnnotation.types.some((t) => includesUndefined(t));
case "TSUndefinedKeyword":

Check failure on line 94 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / run-rules-on-codebase

Missing braces in case clause
return true;
default:

Check failure on line 96 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / run-rules-on-codebase

Missing braces in case clause
return false;
}
};

const hasMixedReturns = (functionNode) => {

Check warning on line 101 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Arrow function has a complexity of 23. Maximum allowed is 20
let hasNonUndefined = false;
let hasExplicitUndefined = false;
const stack = [];

if (
functionNode.type === "ArrowFunctionExpression" &&
functionNode.body &&
functionNode.body.type !== "BlockStatement"
) {
if (
functionNode.body.type === "Identifier" &&
functionNode.body.name === "undefined"
) {
hasExplicitUndefined = true;
} else {
hasNonUndefined = true;
}
} else {
stack.push(functionNode.body);
while (stack.length) {

Check failure on line 121 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / run-rules-on-codebase

Use `.length > 0` when checking length is not zero
const node = stack.pop();
if (!node || typeof node !== "object") continue;
if (node.type === "ReturnStatement") {
if (node.argument) {

Check failure on line 125 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / run-rules-on-codebase

Unexpected `if` as the only statement in a `if` block without `else`
if (

Check warning on line 126 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Blocks are nested too deeply (5). Maximum allowed is 4
node.argument.type === "Identifier" &&
node.argument.name === "undefined"
) {
hasExplicitUndefined = true;
} else {
hasNonUndefined = true;
}
}
}
for (const key in node) {
if (!Object.prototype.hasOwnProperty.call(node, key)) continue;
// Skip the parent property to avoid cycles.
if (key === "parent") continue;
const child = node[key];
if (Array.isArray(child)) {
for (let i = child.length - 1; i >= 0; i--) {

Check failure on line 142 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / run-rules-on-codebase

The variable `i` should be named `index`. A more descriptive name will do too

Check warning on line 142 in rules/no-useless-undefined.js

View workflow job for this annotation

GitHub Actions / lint-test (ubuntu-latest)

Blocks are nested too deeply (5). Maximum allowed is 4
stack.push(child[i]);
}
} else if (child && typeof child.type === "string") {
stack.push(child);
}
}
if (hasExplicitUndefined && hasNonUndefined) break;
}
}

return hasExplicitUndefined && hasNonUndefined;
};

const isFunctionBindCall = node =>
Expand All @@ -90,11 +167,24 @@
const create = context => {
const {sourceCode} = context;

const options = {
checkArguments: true,
checkArrowFunctionBody: true,
allowMixedReturns: false,
...context.options[0],
};

const getProblem = (node, fix, checkFunctionReturnType) => {
if (checkFunctionReturnType) {
const functionNode = getFunction(sourceCode.getScope(node));
if (functionNode?.returnType) {
return;
const functionNode = getFunctionNode(node);
if (functionNode) {
const returnType = functionNode.returnType || (functionNode.value && functionNode.value.returnType);
if (returnType && includesUndefined(returnType.typeAnnotation)) {
return;
}
if (options.allowMixedReturns && hasMixedReturns(functionNode, sourceCode)) {
return;
}
}
}

Expand All @@ -105,12 +195,6 @@
};
};

const options = {
checkArguments: true,
checkArrowFunctionBody: true,
...context.options[0],
};

const removeNodeAndLeadingSpace = (node, fixer) =>
replaceNodeOrTokenAndSpacesBefore(node, '', fixer, sourceCode);

Expand Down Expand Up @@ -287,6 +371,9 @@
checkArrowFunctionBody: {
type: 'boolean',
},
allowMixedReturns: {
type: 'boolean',
},
},
},
];
Expand Down
Loading