-
Notifications
You must be signed in to change notification settings - Fork 238
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(prefer-to-be-undefined): convert to typescript (#395)
- Loading branch information
Showing
4 changed files
with
78 additions
and
144 deletions.
There are no files selected for viewing
5 changes: 3 additions & 2 deletions
5
.../__tests__/prefer-to-be-undefined.test.js → .../__tests__/prefer-to-be-undefined.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { | ||
AST_NODE_TYPES, | ||
TSESTree, | ||
} from '@typescript-eslint/experimental-utils'; | ||
import { | ||
ParsedEqualityMatcherCall, | ||
ParsedExpectMatcher, | ||
createRule, | ||
isExpectCall, | ||
isParsedEqualityMatcherCall, | ||
parseExpectCall, | ||
} from './tsUtils'; | ||
|
||
interface UndefinedIdentifier extends TSESTree.Identifier { | ||
name: 'undefined'; | ||
} | ||
|
||
const isUndefinedIdentifier = ( | ||
node: TSESTree.Node, | ||
): node is UndefinedIdentifier => | ||
node.type === AST_NODE_TYPES.Identifier && node.name === 'undefined'; | ||
|
||
/** | ||
* Checks if the given `ParsedExpectMatcher` is a call to one of the equality matchers, | ||
* with a `undefined` identifier as the sole argument. | ||
* | ||
* @param {ParsedExpectMatcher} matcher | ||
* | ||
* @return {matcher is ParsedEqualityMatcherCall<UndefinedIdentifier>} | ||
*/ | ||
const isUndefinedEqualityMatcher = ( | ||
matcher: ParsedExpectMatcher, | ||
): matcher is ParsedEqualityMatcherCall<UndefinedIdentifier> => | ||
isParsedEqualityMatcherCall(matcher) && | ||
isUndefinedIdentifier(matcher.arguments[0]); | ||
|
||
export default createRule({ | ||
name: __filename, | ||
meta: { | ||
docs: { | ||
category: 'Best Practices', | ||
description: 'Suggest using `toBeUndefined()`', | ||
recommended: false, | ||
}, | ||
messages: { | ||
useToBeUndefined: 'Use toBeUndefined() instead', | ||
}, | ||
fixable: 'code', | ||
type: 'suggestion', | ||
schema: [], | ||
}, | ||
defaultOptions: [], | ||
create(context) { | ||
return { | ||
CallExpression(node) { | ||
if (!isExpectCall(node)) { | ||
return; | ||
} | ||
|
||
const { matcher } = parseExpectCall(node); | ||
|
||
if (matcher && isUndefinedEqualityMatcher(matcher)) { | ||
context.report({ | ||
fix: fixer => [ | ||
fixer.replaceText(matcher.node.property, 'toBeUndefined'), | ||
fixer.remove(matcher.arguments[0]), | ||
], | ||
messageId: 'useToBeUndefined', | ||
node: matcher.node.property, | ||
}); | ||
} | ||
}, | ||
}; | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,90 +1,2 @@ | ||
import { basename } from 'path'; | ||
import { version } from '../../package.json'; | ||
|
||
const REPO_URL = 'https://github.com/jest-community/eslint-plugin-jest'; | ||
|
||
export const expectCase = node => | ||
node && node.callee && node.callee.name === 'expect'; | ||
|
||
export const expectCaseWithParent = node => | ||
expectCase(node) && | ||
node.parent && | ||
node.parent.type === 'MemberExpression' && | ||
node.parent.parent; | ||
|
||
export const expectNotCase = node => | ||
expectCase(node) && | ||
node.parent.parent.type === 'MemberExpression' && | ||
methodName(node) === 'not'; | ||
|
||
export const expectResolvesCase = node => | ||
expectCase(node) && | ||
node.parent.parent.type === 'MemberExpression' && | ||
methodName(node) === 'resolves'; | ||
|
||
export const expectRejectsCase = node => | ||
expectCase(node) && | ||
node.parent.parent.type === 'MemberExpression' && | ||
methodName(node) === 'rejects'; | ||
|
||
export const expectToBeCase = (node, arg) => | ||
!( | ||
expectNotCase(node) || | ||
expectResolvesCase(node) || | ||
expectRejectsCase(node) | ||
) && | ||
expectCase(node) && | ||
methodName(node) === 'toBe' && | ||
argument(node) && | ||
(argument(node).name === 'undefined' && arg === undefined); | ||
|
||
export const expectNotToBeCase = (node, arg) => | ||
expectNotCase(node) && | ||
methodName2(node) === 'toBe' && | ||
argument2(node) && | ||
(argument2(node).name === 'undefined' && arg === undefined); | ||
|
||
export const expectToEqualCase = (node, arg) => | ||
!( | ||
expectNotCase(node) || | ||
expectResolvesCase(node) || | ||
expectRejectsCase(node) | ||
) && | ||
expectCase(node) && | ||
methodName(node) === 'toEqual' && | ||
argument(node) && | ||
(argument(node).name === 'undefined' && arg === undefined); | ||
|
||
export const expectNotToEqualCase = (node, arg) => | ||
expectNotCase(node) && | ||
methodName2(node) === 'toEqual' && | ||
argument2(node) && | ||
(argument2(node).name === 'undefined' && arg === undefined); | ||
|
||
export const method = node => node.parent.property; | ||
|
||
export const method2 = node => node.parent.parent.property; | ||
|
||
const methodName = node => method(node) && method(node).name; | ||
|
||
const methodName2 = node => method2(node) && method2(node).name; | ||
|
||
export const argument = node => | ||
node.parent.parent.arguments && node.parent.parent.arguments[0]; | ||
|
||
export const argument2 = node => | ||
node.parent.parent.parent.arguments && node.parent.parent.parent.arguments[0]; | ||
|
||
/** | ||
* Generates the URL to documentation for the given rule name. It uses the | ||
* package version to build the link to a tagged version of the | ||
* documentation file. | ||
* | ||
* @param {string} filename - Name of the eslint rule | ||
* @returns {string} URL to the documentation for the given rule | ||
*/ | ||
export const getDocsUrl = filename => { | ||
const ruleName = basename(filename, '.js'); | ||
|
||
return `${REPO_URL}/blob/v${version}/docs/rules/${ruleName}.md`; | ||
}; |