diff --git a/.vscode/settings.json b/.vscode/settings.json index 6209862..3c63134 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -21,6 +21,7 @@ "instanceof", "isnan", "itertools", + "jsxmember", "kosaraju", "msvc", "musleabihf", diff --git a/__test__/check_oxlint/__snapshots__/index.spec.ts.snap b/__test__/check_oxlint/__snapshots__/index.spec.ts.snap new file mode 100644 index 0000000..54485c8 --- /dev/null +++ b/__test__/check_oxlint/__snapshots__/index.spec.ts.snap @@ -0,0 +1,32 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`No phantom dependencies 1`] = ` +[ + { + "code": "eslint-plugin-unicorn(no-instanceof-array)", + "fileName": "index.js", + "help": "The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js.", + "labels": [ + { + "loc": { + "end": { + "col": 27, + "line": 2, + }, + "start": { + "col": 5, + "line": 2, + }, + }, + "span": { + "length": 22, + "offset": 14, + }, + }, + ], + "message": "Use \`Array.isArray()\` instead of \`instanceof Array\`.", + "severity": "error", + "url": "https://oxc.rs/docs/guide/usage/linter/rules/unicorn/no-instanceof-array.html", + }, +] +`; diff --git a/__test__/check_oxlint/fixtures/index.js b/__test__/check_oxlint/fixtures/index.js new file mode 100644 index 0000000..57908d3 --- /dev/null +++ b/__test__/check_oxlint/fixtures/index.js @@ -0,0 +1,2 @@ +// 你好 +if (param instanceof Array) console.log(456); diff --git a/__test__/check_oxlint/index.spec.ts b/__test__/check_oxlint/index.spec.ts new file mode 100644 index 0000000..8ec80b6 --- /dev/null +++ b/__test__/check_oxlint/index.spec.ts @@ -0,0 +1,21 @@ +import { expect, test } from "vitest"; +import { checkOxlint } from "../../index"; +import { fileURLToPath } from "node:url"; +import path from "node:path"; +import { dirname } from "node:path"; + +const __filename = fileURLToPath(import.meta.url); + +test("No phantom dependencies", async () => { + const cwd = path.resolve(dirname(__filename), "fixtures"); + const res = await checkOxlint( + JSON.stringify({ + rules: { + "unicorn/no-instanceof-array": "error", + }, + }), + { cwd }, + ); + + console.log(res.at(0)?.labels); +}); diff --git a/crates/check_oxlint/src/lib.rs b/crates/check_oxlint/src/lib.rs index af97301..291bdde 100644 --- a/crates/check_oxlint/src/lib.rs +++ b/crates/check_oxlint/src/lib.rs @@ -1,5 +1,6 @@ use std::{fmt::Display, rc::Rc, sync::Arc}; +use beans::{Location, Span}; use napi_derive::napi; use oxc_diagnostics::Severity; use oxc_linter::{FixKind, LinterBuilder, Oxlintrc}; @@ -17,6 +18,7 @@ pub struct CheckOxlintLabelsSpan { #[derive(Debug, Clone, Serialize)] pub struct CheckOxlintLabelsResponse { pub span: CheckOxlintLabelsSpan, + pub loc: Location, } #[napi(object)] @@ -62,6 +64,8 @@ pub fn check_oxlint( )); let semantic = Rc::new(semantic); + let source_text = semantic.source_text(); + let diagnostics = linter.run(&path, semantic, module_record); let responses = diagnostics @@ -84,11 +88,19 @@ pub fn check_oxlint( .as_ref() .map(|v| { v.iter() - .map(|l| CheckOxlintLabelsResponse { - span: CheckOxlintLabelsSpan { - offset: l.offset() as u32, - length: l.len() as u32, - }, + .map(|l| { + let loc = Location::with_source(&source_text, Span { + start: l.offset() as u32, + end: l.offset() as u32 + l.len() as u32, + }); + + return CheckOxlintLabelsResponse { + span: CheckOxlintLabelsSpan { + offset: l.offset() as u32, + length: l.len() as u32, + }, + loc, + }; }) .collect::>() }) diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__console.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__console.snap index f79cede..1608567 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__console.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__console.snap @@ -15,6 +15,16 @@ snapshot_kind: text "span": { "offset": 0, "length": 11 + }, + "loc": { + "start": { + "line": 1, + "col": 1 + }, + "end": { + "line": 1, + "col": 12 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__debugger.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__debugger.snap index 158caff..d42ecca 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__debugger.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__debugger.snap @@ -15,6 +15,16 @@ snapshot_kind: text "span": { "offset": 0, "length": 9 + }, + "loc": { + "start": { + "line": 1, + "col": 1 + }, + "end": { + "line": 1, + "col": 10 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__for_direction.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__for_direction.snap index 74f94e3..e0eac81 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__for_direction.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__for_direction.snap @@ -15,12 +15,32 @@ snapshot_kind: text "span": { "offset": 16, "length": 6 + }, + "loc": { + "start": { + "line": 1, + "col": 17 + }, + "end": { + "line": 1, + "col": 23 + } } }, { "span": { "offset": 24, "length": 3 + }, + "loc": { + "start": { + "line": 1, + "col": 25 + }, + "end": { + "line": 1, + "col": 28 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__getter_return.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__getter_return.snap index e5ecd9a..b878446 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__getter_return.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__getter_return.snap @@ -15,6 +15,16 @@ snapshot_kind: text "span": { "offset": 23, "length": 44 + }, + "loc": { + "start": { + "line": 2, + "col": 10 + }, + "end": { + "line": 4, + "col": 3 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_async_promise_executor.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_async_promise_executor.snap index 1462a49..5903619 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_async_promise_executor.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_async_promise_executor.snap @@ -15,6 +15,16 @@ snapshot_kind: text "span": { "offset": 12, "length": 5 + }, + "loc": { + "start": { + "line": 1, + "col": 13 + }, + "end": { + "line": 1, + "col": 18 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_case_declarations.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_case_declarations.snap index bff1fd9..61dad1f 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_case_declarations.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_case_declarations.snap @@ -15,6 +15,16 @@ snapshot_kind: text "span": { "offset": 26, "length": 3 + }, + "loc": { + "start": { + "line": 3, + "col": 3 + }, + "end": { + "line": 3, + "col": 6 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_class_assign.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_class_assign.snap index 4425c70..40c6060 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_class_assign.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_class_assign.snap @@ -15,12 +15,32 @@ snapshot_kind: text "span": { "offset": 6, "length": 1 + }, + "loc": { + "start": { + "line": 1, + "col": 7 + }, + "end": { + "line": 1, + "col": 8 + } } }, { "span": { "offset": 11, "length": 1 + }, + "loc": { + "start": { + "line": 2, + "col": 1 + }, + "end": { + "line": 2, + "col": 2 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_compare_neg_zero.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_compare_neg_zero.snap index 6753285..5acc06b 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_compare_neg_zero.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_compare_neg_zero.snap @@ -15,6 +15,16 @@ snapshot_kind: text "span": { "offset": 4, "length": 8 + }, + "loc": { + "start": { + "line": 1, + "col": 5 + }, + "end": { + "line": 1, + "col": 13 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_const_assign.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_const_assign.snap index bf58e0e..85d3069 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_const_assign.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_const_assign.snap @@ -15,12 +15,32 @@ snapshot_kind: text "span": { "offset": 6, "length": 1 + }, + "loc": { + "start": { + "line": 1, + "col": 7 + }, + "end": { + "line": 1, + "col": 8 + } } }, { "span": { "offset": 13, "length": 1 + }, + "loc": { + "start": { + "line": 2, + "col": 1 + }, + "end": { + "line": 2, + "col": 2 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_constant_binary_expression.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_constant_binary_expression.snap index 4b028e8..44dd5ca 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_constant_binary_expression.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_constant_binary_expression.snap @@ -15,6 +15,16 @@ snapshot_kind: text "span": { "offset": 4, "length": 13 + }, + "loc": { + "start": { + "line": 1, + "col": 5 + }, + "end": { + "line": 1, + "col": 18 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_constant_condition.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_constant_condition.snap index 2b4229f..6697df6 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_constant_condition.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_constant_condition.snap @@ -15,6 +15,16 @@ snapshot_kind: text "span": { "offset": 4, "length": 4 + }, + "loc": { + "start": { + "line": 1, + "col": 5 + }, + "end": { + "line": 1, + "col": 9 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_delete_var.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_delete_var.snap index ac7b486..a706ac3 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_delete_var.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_delete_var.snap @@ -15,6 +15,16 @@ snapshot_kind: text "span": { "offset": 7, "length": 8 + }, + "loc": { + "start": { + "line": 2, + "col": 1 + }, + "end": { + "line": 2, + "col": 9 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_class_members.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_class_members.snap index e799235..f50832f 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_class_members.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_class_members.snap @@ -15,12 +15,32 @@ snapshot_kind: text "span": { "offset": 11, "length": 3 + }, + "loc": { + "start": { + "line": 2, + "col": 2 + }, + "end": { + "line": 2, + "col": 5 + } } }, { "span": { "offset": 21, "length": 3 + }, + "loc": { + "start": { + "line": 3, + "col": 2 + }, + "end": { + "line": 3, + "col": 5 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_else_if.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_else_if.snap index 06d15d0..80d4a32 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_else_if.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_else_if.snap @@ -15,12 +15,32 @@ snapshot_kind: text "span": { "offset": 20, "length": 1 + }, + "loc": { + "start": { + "line": 2, + "col": 12 + }, + "end": { + "line": 2, + "col": 13 + } } }, { "span": { "offset": 4, "length": 1 + }, + "loc": { + "start": { + "line": 1, + "col": 5 + }, + "end": { + "line": 1, + "col": 6 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_keys.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_keys.snap index d18d416..1598719 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_keys.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_dupe_keys.snap @@ -15,12 +15,32 @@ snapshot_kind: text "span": { "offset": 15, "length": 3 + }, + "loc": { + "start": { + "line": 2, + "col": 2 + }, + "end": { + "line": 2, + "col": 5 + } } }, { "span": { "offset": 24, "length": 3 + }, + "loc": { + "start": { + "line": 3, + "col": 2 + }, + "end": { + "line": 3, + "col": 5 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_duplicate_case.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_duplicate_case.snap index 0201d23..c6c8b34 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_duplicate_case.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_duplicate_case.snap @@ -15,12 +15,32 @@ snapshot_kind: text "span": { "offset": 19, "length": 1 + }, + "loc": { + "start": { + "line": 2, + "col": 7 + }, + "end": { + "line": 2, + "col": 8 + } } }, { "span": { "offset": 37, "length": 1 + }, + "loc": { + "start": { + "line": 4, + "col": 7 + }, + "end": { + "line": 4, + "col": 8 + } } } ] diff --git a/crates/check_oxlint/tests/snapshots/oxlint_test__no_new_for_builtins.snap b/crates/check_oxlint/tests/snapshots/oxlint_test__no_new_for_builtins.snap index 1795f9b..2a5aa0f 100644 --- a/crates/check_oxlint/tests/snapshots/oxlint_test__no_new_for_builtins.snap +++ b/crates/check_oxlint/tests/snapshots/oxlint_test__no_new_for_builtins.snap @@ -15,6 +15,16 @@ snapshot_kind: text "span": { "offset": 13, "length": 9 + }, + "loc": { + "start": { + "line": 1, + "col": 14 + }, + "end": { + "line": 1, + "col": 23 + } } } ] diff --git a/crates/module_member_usage/src/process.rs b/crates/module_member_usage/src/process.rs index 3156b3d..daf9785 100644 --- a/crates/module_member_usage/src/process.rs +++ b/crates/module_member_usage/src/process.rs @@ -2,7 +2,7 @@ use beans::AstNode; use oxc_ast::{ ast::{ BindingIdentifier, Expression, ImportDeclarationSpecifier, - JSXOpeningElement, + JSXMemberExpression, JSXOpeningElement, }, AstKind, }; @@ -83,105 +83,24 @@ fn each_specifiers<'a>( let responses = specifiers .iter() .map(|spec| { - let imported_name = match spec { - ImportDeclarationSpecifier::ImportSpecifier(import_specifier) => { - import_specifier.imported.name().as_str() - } - ImportDeclarationSpecifier::ImportDefaultSpecifier(_) => ES_DEFAULT, - ImportDeclarationSpecifier::ImportNamespaceSpecifier(_) => ES_NAMESPACE, - }; + // .e.g import {a as b} from 'test' -> a + let imported_name = get_imported_name(spec); let is_default_specifier = is_default_specifier(spec); - let references = get_symbol_references(semantic, spec.local()); - let responses = references - .iter() - .filter_map(|refer| { - let reference_node = get_reference_node(semantic, refer); - let ast_node = AstNode::with_source_and_ast_node( - semantic.source_text(), - reference_node, - ); - let is_in_closing = is_in(&semantic, reference_node, 6, |kind| { - matches!(kind, AstKind::JSXClosingElement(_)) - }) - .is_some(); - - if is_in_closing { - return None; - } - let opening_node = is_in(&semantic, reference_node, 6, |kind| { - matches!(kind, AstKind::JSXOpeningElement(_)) - }); - - if let Some(AstKind::JSXOpeningElement(kind)) = - opening_node.map(|node| node.kind()) - { - let name = get_jsx_opening_element_name( - kind, - is_default_specifier, - imported_name, - ); - - let attributes = get_jsx_props(kind); - - return Some(ModuleMemberUsageResponseItem { - lib_name: source_name.to_string(), - member_name: name.to_string(), - ast_node: ast_node, - props: attributes, - }); - } + let is_namespace_specifier = is_namespace_specifier(spec); - let member_parent_node = - is_in(&semantic, reference_node, 2, |kind| { - matches!(kind, AstKind::MemberExpression(_)) - }); - - if let Some(AstKind::MemberExpression(kind)) = - member_parent_node.map(|node| node.kind()) - { - let name = match kind { - oxc_ast::ast::MemberExpression::ComputedMemberExpression( - computed_member_expression, - ) => match &computed_member_expression.expression { - Expression::StringLiteral(string_literal) => { - string_literal.to_string() - } - Expression::TemplateLiteral(_) - | Expression::Identifier(_) - | Expression::LogicalExpression(_) => { - DYNAMIC_COMPUTED_MEMBER.to_string() - } - _ => UNKNOWN.to_string(), - }, - oxc_ast::ast::MemberExpression::StaticMemberExpression( - static_member_expression, - ) => match &static_member_expression.object { - Expression::Identifier(ident) => ident.name.to_string(), - _ => UNKNOWN.to_string(), - }, - oxc_ast::ast::MemberExpression::PrivateFieldExpression( - private_field_expression, - ) => private_field_expression.field.name.to_string(), - }; - - return Some(ModuleMemberUsageResponseItem { - lib_name: source_name.to_string(), - member_name: name.to_string(), - ast_node: ast_node, - props: vec![], - }); - } + let references = get_symbol_references(semantic, spec.local()); + + let responses = each_reference( + semantic, + source_name, + imported_name, + is_default_specifier, + is_namespace_specifier, + references, + ); - return Some(ModuleMemberUsageResponseItem { - lib_name: source_name.to_string(), - member_name: imported_name.to_string(), - ast_node: ast_node, - props: vec![], - }); - }) - .collect::>(); return responses; }) .flatten() @@ -189,9 +108,117 @@ fn each_specifiers<'a>( return responses; } +fn each_reference<'a>( + semantic: &'a Semantic, + source_name: &str, + imported_name: String, + is_default_specifier: bool, + is_namespace_specifier: bool, + references: Vec<&'a Reference>, +) -> Vec { + references + .iter() + .filter_map(|refer| { + let reference_node = get_reference_node(semantic, refer); + + let is_in_closing = is_in(&semantic, reference_node, 6, |kind| { + matches!(kind, AstKind::JSXClosingElement(_)) + }) + .is_some(); + + if is_in_closing { + return None; + } + + let ast_node = AstNode::with_source_and_ast_node( + semantic.source_text(), + reference_node, + ); + + let opening_node = is_in(&semantic, reference_node, 10, |kind| { + matches!(kind, AstKind::JSXOpeningElement(_)) + }); + + if let Some(AstKind::JSXOpeningElement(kind)) = + opening_node.map(|node| node.kind()) + { + let name = get_jsx_opening_element_name( + kind, + is_default_specifier, + is_namespace_specifier, + imported_name.as_str(), + ); + + let attributes = get_jsx_props(kind); + + return Some(ModuleMemberUsageResponseItem { + lib_name: source_name.to_string(), + member_name: name.to_string(), + ast_node: ast_node, + props: attributes, + }); + } + + let member_parent_node = is_in(&semantic, reference_node, 2, |kind| { + matches!(kind, AstKind::MemberExpression(_)) + }); + + if let Some(AstKind::MemberExpression(kind)) = + member_parent_node.map(|node| node.kind()) + { + let name = match kind { + oxc_ast::ast::MemberExpression::ComputedMemberExpression( + computed_member_expression, + ) => match &computed_member_expression.expression { + Expression::StringLiteral(string_literal) => { + string_literal.to_string() + } + Expression::TemplateLiteral(_) + | Expression::Identifier(_) + | Expression::LogicalExpression(_) => { + DYNAMIC_COMPUTED_MEMBER.to_string() + } + _ => UNKNOWN.to_string(), + }, + oxc_ast::ast::MemberExpression::StaticMemberExpression( + static_member_expression, + ) => { + if is_default_specifier || is_namespace_specifier { + static_member_expression.property.name.to_string() + } else { + match &static_member_expression.object { + Expression::Identifier(ident) => ident.name.to_string(), + _ => UNKNOWN.to_string(), + } + } + } + oxc_ast::ast::MemberExpression::PrivateFieldExpression( + private_field_expression, + ) => private_field_expression.field.name.to_string(), + }; + + return Some(ModuleMemberUsageResponseItem { + lib_name: source_name.to_string(), + member_name: name.to_string(), + ast_node: ast_node, + props: vec![], + }); + } + + return Some(ModuleMemberUsageResponseItem { + lib_name: source_name.to_string(), + member_name: imported_name.to_string(), + ast_node: ast_node, + props: vec![], + }); + }) + .collect::>() +} + fn get_jsx_opening_element_name( kind: &JSXOpeningElement, is_default_specifier: bool, + is_namespace_specifier: bool, imported_name: &str, ) -> String { match &kind.name { @@ -203,18 +230,22 @@ fn get_jsx_opening_element_name( namespace_name.property.name.to_string() } oxc_ast::ast::JSXElementName::MemberExpression(jsx_member_expr) => { - if is_default_specifier { - imported_name.to_string() + if is_default_specifier || is_namespace_specifier { + let mut path = vec![]; + get_member_expression_name(&jsx_member_expr, &mut path); + path + .last() + .map_or(UNKNOWN.to_string(), |last| last.to_string()) } else { match &jsx_member_expr.object { oxc_ast::ast::JSXMemberExpressionObject::IdentifierReference(_) => { - jsx_member_expr.property.name.to_string() + imported_name.to_string() } oxc_ast::ast::JSXMemberExpressionObject::MemberExpression( jsx_member_expression, ) => jsx_member_expression.property.name.to_string(), oxc_ast::ast::JSXMemberExpressionObject::ThisExpression(_) => { - "this".to_string() + "This".to_string() } } } @@ -223,6 +254,24 @@ fn get_jsx_opening_element_name( } } +fn get_member_expression_name( + jsx_member_expr: &JSXMemberExpression, + path: &mut Vec, +) -> String { + path.push(jsx_member_expr.property.name.to_string()); + match &jsx_member_expr.object { + oxc_ast::ast::JSXMemberExpressionObject::IdentifierReference( + identifier_reference, + ) => identifier_reference.name.to_string(), + oxc_ast::ast::JSXMemberExpressionObject::MemberExpression( + jsxmember_expression, + ) => get_member_expression_name(&jsxmember_expression, path), + oxc_ast::ast::JSXMemberExpressionObject::ThisExpression(_) => { + "This".to_string() + } + } +} + fn get_symbol_references<'a>( semantic: &'a Semantic, binding: &BindingIdentifier, @@ -264,13 +313,34 @@ fn is_in<'a>( None } +fn get_imported_name(specifier: &ImportDeclarationSpecifier) -> String { + match specifier { + ImportDeclarationSpecifier::ImportSpecifier(import_specifier) => { + import_specifier.imported.name().as_str().to_string() + } + ImportDeclarationSpecifier::ImportDefaultSpecifier(_) => { + ES_DEFAULT.to_string() + } + ImportDeclarationSpecifier::ImportNamespaceSpecifier(_) => { + ES_NAMESPACE.to_string() + } + } +} + fn is_default_specifier(specifier: &ImportDeclarationSpecifier) -> bool { match specifier { ImportDeclarationSpecifier::ImportSpecifier(import_specifier) => { - !(import_specifier.imported.name() == "default") + import_specifier.imported.name() == "default" } - ImportDeclarationSpecifier::ImportDefaultSpecifier(_) - | ImportDeclarationSpecifier::ImportNamespaceSpecifier(_) => false, + ImportDeclarationSpecifier::ImportDefaultSpecifier(_) => true, + _ => false, + } +} + +fn is_namespace_specifier(specifier: &ImportDeclarationSpecifier) -> bool { + match specifier { + ImportDeclarationSpecifier::ImportNamespaceSpecifier(_) => true, + _ => false, } } @@ -527,6 +597,8 @@ mod tests { .map(|(key, group)| (key, group.count())) .collect::>(); + println!("grouped: {:?}", grouped); + assert_eq!(grouped.keys().len(), 3); assert_eq!(grouped["method"], 1); assert_eq!(grouped["named1"], 2); @@ -540,7 +612,7 @@ mod tests { &r#" import * as Lib from 'lib'; function Component() { - return ; + return ; } "#, ); @@ -607,6 +679,7 @@ mod tests { } "#, ); + assert_eq!(result.len(), 1); assert_eq!(result[0].lib_name, "react"); assert_eq!(result[0].member_name, "Fragment"); @@ -619,11 +692,16 @@ mod tests { &r#" import * as React from 'react'; function Component() { - return Hello; + return +
world
+ Hello +
; } "#, ); + println!("result: {:?}", result); + assert_eq!(result.len(), 1); assert_eq!(result[0].lib_name, "react"); assert_eq!(result[0].member_name, "Fragment"); @@ -658,6 +736,10 @@ mod tests { "#, ); + // for item in result.iter() { + // println!("item: {:?} {:?}", item.lib_name, item.member_name); + // } + assert_eq!(result.len(), 3); assert!(result .iter() diff --git a/package.json b/package.json index f3fa8f7..31a9048 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@shined/source-code-diagnosis", - "version": "0.0.85", + "version": "0.0.86", "main": "index.js", "types": "index.d.ts", "napi": {