Skip to content
Merged
Show file tree
Hide file tree
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
44 changes: 32 additions & 12 deletions crates/oxc_linter/src/rules/react/display_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,17 +151,20 @@ impl Rule for DisplayName {

// Phase 1: Iterate symbols to find components with declarations
for symbol_id in ctx.scoping().symbol_ids() {
let declaration = ctx.scoping().symbol_declaration(symbol_id);
let decl_node = ctx.nodes().get_node(declaration);
let component_info =
ctx.scoping().symbol_declarations(symbol_id).find_map(|declaration| {
let decl_node = ctx.nodes().get_node(declaration);
is_react_component_node(
decl_node,
ctx,
&mut version_cache,
ignore_transpiler_name,
check_context_objects,
)
});

// First check if the declaration itself is a component
if let Some(component_info) = is_react_component_node(
decl_node,
ctx,
&mut version_cache,
ignore_transpiler_name,
check_context_objects,
) {
if let Some(component_info) = component_info {
// If component has a name and ignoreTranspilerName is false and it's not a context,
// the name itself is considered a valid displayName
if component_info.name.is_some()
Expand All @@ -178,9 +181,13 @@ impl Rule for DisplayName {
} else if check_context_objects {
// If the declaration isn't a component, check if any write references assign createContext()
// This handles: var Hello; Hello = createContext();
if let Some(component_info) =
check_context_assignment_references(symbol_id, decl_node, ctx)
{
let context_assignment_info =
ctx.scoping().symbol_declarations(symbol_id).find_map(|declaration| {
let decl_node = ctx.nodes().get_node(declaration);
check_context_assignment_references(symbol_id, decl_node, ctx)
});

if let Some(component_info) = context_assignment_info {
// Check if this symbol has a displayName assignment
if !has_display_name_via_semantic(symbol_id, component_info.name.as_ref(), ctx)
{
Expand Down Expand Up @@ -2151,6 +2158,19 @@ fn test() {
"
import { createContext } from 'react';

interface PostHogGroupContext {
value: string;
}

const PostHogGroupContext = createContext<PostHogGroupContext | null>(null);
",
Some(serde_json::json!([{ "checkContextObjects": true }])),
None,
),
(
"
import { createContext } from 'react';

var Hello;
Hello = createContext();
",
Expand Down
9 changes: 9 additions & 0 deletions crates/oxc_linter/src/snapshots/react_display_name.snap
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,15 @@ source: crates/oxc_linter/src/tester.rs
╰────
help: Add a `displayName` property to the context.

⚠ eslint-plugin-react(display-name): Context definition is missing display name.
╭─[display_name.tsx:8:27]
7 │
8 │ const PostHogGroupContext = createContext<PostHogGroupContext | null>(null);
· ───────────────────
9 │
╰────
help: Add a `displayName` property to the context.

⚠ eslint-plugin-react(display-name): Context definition is missing display name.
╭─[display_name.tsx:5:21]
4 │ var Hello;
Expand Down
Loading