refactor(linter): remove all old parse_expect_jest_fn_call (#1259)

This commit is contained in:
Wenzhe Wang 2023-11-13 14:33:41 +08:00 committed by GitHub
parent 472707c04e
commit f3788eec31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 62 additions and 68 deletions

View file

@ -60,7 +60,7 @@ impl Rule for NoAliasMethods {
fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) {
let node = possible_jest_node.node;
if let AstKind::CallExpression(call_expr) = node.kind() {
if let Some(jest_fn_call) = parse_expect_jest_fn_call(call_expr, node, ctx) {
if let Some(jest_fn_call) = parse_expect_jest_fn_call(call_expr, possible_jest_node, ctx) {
let parsed_expect_call = jest_fn_call;
let Some(matcher) = parsed_expect_call.matcher() else {
return;

View file

@ -9,7 +9,11 @@ use oxc_diagnostics::{
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use crate::{context::LintContext, rule::Rule, utils::parse_expect_jest_fn_call, AstNode};
use crate::{
context::LintContext,
rule::Rule,
utils::{collect_possible_jest_call_node, parse_expect_jest_fn_call, PossibleJestNode},
};
#[derive(Debug, Error, Diagnostic)]
#[error("eslint-plugin-jest(no-interpolation-in-snapshots): Do not use string interpolation inside of snapshots")]
@ -56,26 +60,35 @@ declare_oxc_lint!(
);
impl Rule for NoInterpolationInSnapshots {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::CallExpression(call_expr) = node.kind() else { return };
let Some(jest_fn_call) = parse_expect_jest_fn_call(call_expr, node, ctx) else { return };
let Some(matcher) = jest_fn_call.matcher() else {
return;
};
if matcher.is_name_unequal("toMatchInlineSnapshot")
&& matcher.is_name_unequal("toThrowErrorMatchingInlineSnapshot")
{
return;
fn run_once(&self, ctx: &LintContext) {
for possible_jest_node in &collect_possible_jest_call_node(ctx) {
run(possible_jest_node, ctx);
}
}
}
// Check all since the optional 'propertyMatchers' argument might be present
// `.toMatchInlineSnapshot(propertyMatchers?, inlineSnapshot)`
for arg in jest_fn_call.args {
if let Argument::Expression(Expression::TemplateLiteral(template_lit)) = arg {
if !template_lit.expressions.is_empty() {
ctx.diagnostic(NoInterpolationInSnapshotsDiagnostic(template_lit.span));
}
fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) {
let node = possible_jest_node.node;
let AstKind::CallExpression(call_expr) = node.kind() else { return };
let Some(jest_fn_call) = parse_expect_jest_fn_call(call_expr, possible_jest_node, ctx) else {
return;
};
let Some(matcher) = jest_fn_call.matcher() else {
return;
};
if matcher.is_name_unequal("toMatchInlineSnapshot")
&& matcher.is_name_unequal("toThrowErrorMatchingInlineSnapshot")
{
return;
}
// Check all since the optional 'propertyMatchers' argument might be present
// `.toMatchInlineSnapshot(propertyMatchers?, inlineSnapshot)`
for arg in jest_fn_call.args {
if let Argument::Expression(Expression::TemplateLiteral(template_lit)) = arg {
if !template_lit.expressions.is_empty() {
ctx.diagnostic(NoInterpolationInSnapshotsDiagnostic(template_lit.span));
}
}
}

View file

@ -13,9 +13,9 @@ use crate::{
context::LintContext,
rule::Rule,
utils::{
collect_possible_jest_call_node, get_node_name, parse_expect_jest_fn_call_new,
collect_possible_jest_call_node, get_node_name, parse_expect_jest_fn_call,
parse_general_jest_fn_call, JestFnKind, JestGeneralFnKind,
KnownMemberExpressionParentKindNew, ParsedExpectFnCallNew, PossibleJestNode,
KnownMemberExpressionParentKindNew, ParsedExpectFnCall, PossibleJestNode,
},
AstNode,
};
@ -88,11 +88,11 @@ impl NoStandaloneExpect {
let AstKind::CallExpression(call_expr) = node.kind() else {
return;
};
let Some(jest_fn_call) = parse_expect_jest_fn_call_new(call_expr, possible_jest_node, ctx)
let Some(jest_fn_call) = parse_expect_jest_fn_call(call_expr, possible_jest_node, ctx)
else {
return;
};
let ParsedExpectFnCallNew { head, members, .. } = jest_fn_call;
let ParsedExpectFnCall { head, members, .. } = jest_fn_call;
// only report `expect.hasAssertions` & `expect.assertions` member calls
if members.len() == 1

View file

@ -12,7 +12,9 @@ use oxc_span::{Atom, GetSpan, Span};
use crate::{
context::LintContext,
rule::Rule,
utils::{parse_expect_jest_fn_call, ExpectError},
utils::{
collect_possible_jest_call_node, parse_expect_jest_fn_call, ExpectError, PossibleJestNode,
},
AstNode,
};
@ -88,9 +90,21 @@ impl Rule for ValidExpect {
Self { async_matchers, min_args, max_args, always_await }
}
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
fn run_once(&self, ctx: &LintContext) {
for possible_jest_node in &collect_possible_jest_call_node(ctx) {
self.run(possible_jest_node, ctx);
}
}
}
impl ValidExpect {
fn run<'a>(&self, possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) {
let node = possible_jest_node.node;
let AstKind::CallExpression(call_expr) = node.kind() else { return };
let Some(jest_fn_call) = parse_expect_jest_fn_call(call_expr, node, ctx) else { return };
let Some(jest_fn_call) = parse_expect_jest_fn_call(call_expr, possible_jest_node, ctx)
else {
return;
};
let reporting_span = jest_fn_call.expect_error.map_or(call_expr.span, |_| {
find_top_most_member_expression(node, ctx).map_or(call_expr.span, GetSpan::span)
});

View file

@ -15,20 +15,18 @@ use crate::LintContext;
mod parse_jest_fn;
use crate::utils::jest::parse_jest_fn::ParsedJestFnCall;
pub use crate::utils::jest::parse_jest_fn::{
parse_jest_fn_call, ExpectError, KnownMemberExpressionParentKind,
KnownMemberExpressionProperty, MemberExpressionElement, ParsedExpectFnCall,
parse_jest_fn_call, KnownMemberExpressionParentKind, KnownMemberExpressionProperty,
MemberExpressionElement,
};
mod parse_jest_fn_new;
pub use crate::utils::jest::parse_jest_fn_new::{
parse_jest_fn_call as parse_jest_fn_call_new,
parse_jest_fn_call as parse_jest_fn_call_new, ExpectError,
KnownMemberExpressionParentKind as KnownMemberExpressionParentKindNew,
KnownMemberExpressionProperty as KnownMemberExpressionPropertyNew,
MemberExpressionElement as MemberExpressionElementNew,
ParsedExpectFnCall as ParsedExpectFnCallNew, ParsedGeneralJestFnCall,
ParsedJestFnCall as ParsedJestFnCallNew,
MemberExpressionElement as MemberExpressionElementNew, ParsedExpectFnCall,
ParsedGeneralJestFnCall, ParsedJestFnCall as ParsedJestFnCallNew,
};
const JEST_METHOD_NAMES: phf::Set<&'static str> = phf_set![
@ -132,23 +130,10 @@ pub fn parse_general_jest_fn_call<'a>(
}
pub fn parse_expect_jest_fn_call<'a>(
call_expr: &'a CallExpression<'a>,
node: &AstNode<'a>,
ctx: &LintContext<'a>,
) -> Option<ParsedExpectFnCall<'a>> {
let jest_fn_call = parse_jest_fn_call(call_expr, node, ctx)?;
if let ParsedJestFnCall::ExpectFnCall(jest_fn_call) = jest_fn_call {
return Some(jest_fn_call);
}
None
}
pub fn parse_expect_jest_fn_call_new<'a>(
call_expr: &'a CallExpression<'a>,
possible_jest_node: &PossibleJestNode<'a, '_>,
ctx: &LintContext<'a>,
) -> Option<ParsedExpectFnCallNew<'a>> {
) -> Option<ParsedExpectFnCall<'a>> {
let jest_fn_call = parse_jest_fn_call_new(call_expr, possible_jest_node, ctx)?;
if let ParsedJestFnCallNew::ExpectFnCall(jest_fn_call) = jest_fn_call {
@ -188,13 +173,11 @@ pub fn collect_possible_jest_call_node<'a, 'b>(
vec![]
};
// The longest length of Jest chains is 4, and it may be a TaggedTemplateExpression, e.g.`it.concurrent.only.each``()`.
// We take 5 ancestors of node and collect all Call Expression.
// The invalid Jest Call Expression will be bypassed in `parse_jest_fn_call`
// get the longest valid chain of Jest Call Expression
reference_id_with_original_list.iter().fold(vec![], |mut acc, id_with_original| {
let (reference_id, original) = id_with_original;
let mut id = ctx.symbols().get_reference(*reference_id).node_id();
for _ in 0..5 {
loop {
let parent = ctx.nodes().parent_node(id);
if let Some(parent) = parent {
let parent_kind = parent.kind();

View file

@ -371,16 +371,6 @@ pub struct ParsedExpectFnCall<'a> {
pub expect_error: Option<ExpectError>,
}
impl<'a> ParsedExpectFnCall<'a> {
pub fn matcher(&self) -> Option<&KnownMemberExpressionProperty<'a>> {
let matcher_index = self.matcher_index?;
self.members.get(matcher_index)
}
pub fn modifiers(&self) -> Vec<&KnownMemberExpressionProperty<'a>> {
self.modifier_indices.iter().filter_map(|i| self.members.get(*i)).collect::<Vec<_>>()
}
}
struct ResolvedJestFn<'a> {
pub local: &'a Atom,
pub original: Option<&'a Atom>,
@ -463,12 +453,6 @@ impl<'a> MemberExpressionElement<'a> {
MemberExpression::PrivateFieldExpression(_) => None,
}
}
pub fn is_string_literal(&self) -> bool {
matches!(
self,
Self::Expression(Expression::StringLiteral(_) | Expression::TemplateLiteral(_))
)
}
}
struct NodeChainParams<'a> {