From f7c4c350cafca9e2fe2ce76e1d334cb53e625296 Mon Sep 17 00:00:00 2001 From: "codeflash-ai[bot]" <148906541+codeflash-ai[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 03:27:24 +0000 Subject: [PATCH 1/3] Optimize _extract_child_components I replaced the per-match Match object creation (finditer + group(1)) with re.findall to get the group strings directly and removed matches in bulk via set operations. This reduces object allocations and Python-level loop overhead, giving measurable speed and memory improvements on large inputs while preserving behavior and output ordering. --- .../languages/javascript/frameworks/react/context.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/codeflash/languages/javascript/frameworks/react/context.py b/codeflash/languages/javascript/frameworks/react/context.py index d4ebaf3d1..25e2fd097 100644 --- a/codeflash/languages/javascript/frameworks/react/context.py +++ b/codeflash/languages/javascript/frameworks/react/context.py @@ -20,6 +20,8 @@ from codeflash.languages.javascript.frameworks.react.discovery import ReactComponentInfo from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer +_BUILTIN_COMPONENTS = frozenset(("React.Fragment", "Fragment", "Suspense", "React.Suspense")) + HOOK_PATTERN = re.compile(r"\b(use[A-Z]\w*)\s*\(") JSX_COMPONENT_RE = re.compile(r"<([A-Z][a-zA-Z0-9.]*)") @@ -169,12 +171,10 @@ def _extract_hook_usages(component_source: str) -> list[HookUsage]: def _extract_child_components(component_source: str, analyzer: TreeSitterAnalyzer, full_source: str) -> list[str]: """Find child component names rendered in JSX.""" - children = set() - for match in JSX_COMPONENT_RE.finditer(component_source): - name = match.group(1) - # Skip React built-ins like React.Fragment - if name not in ("React.Fragment", "Fragment", "Suspense", "React.Suspense"): - children.add(name) + children = set(JSX_COMPONENT_RE.findall(component_source)) + # Skip React built-ins like React.Fragment + if children: + children.difference_update(_BUILTIN_COMPONENTS) return sorted(children) From 12d8facad26dc5cf4e2f9e912f7b33e85c9cb730 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 03:29:51 +0000 Subject: [PATCH 2/3] style: auto-fix linting issues --- .../languages/javascript/frameworks/detector.py | 5 ++++- .../javascript/frameworks/react/discovery.py | 9 +++------ .../javascript/frameworks/react/profiler.py | 12 ++++-------- codeflash/languages/javascript/treesitter_utils.py | 4 ++-- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/codeflash/languages/javascript/frameworks/detector.py b/codeflash/languages/javascript/frameworks/detector.py index 013de47f5..f4905c593 100644 --- a/codeflash/languages/javascript/frameworks/detector.py +++ b/codeflash/languages/javascript/frameworks/detector.py @@ -10,7 +10,10 @@ import logging from dataclasses import dataclass, field from functools import lru_cache -from pathlib import Path +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from pathlib import Path logger = logging.getLogger(__name__) diff --git a/codeflash/languages/javascript/frameworks/react/discovery.py b/codeflash/languages/javascript/frameworks/react/discovery.py index 9e39de817..d4f30a9e6 100644 --- a/codeflash/languages/javascript/frameworks/react/discovery.py +++ b/codeflash/languages/javascript/frameworks/react/discovery.py @@ -10,10 +10,11 @@ import re from dataclasses import dataclass from enum import Enum -from pathlib import Path from typing import TYPE_CHECKING if TYPE_CHECKING: + from pathlib import Path + from tree_sitter import Node from codeflash.languages.javascript.treesitter import FunctionNode, TreeSitterAnalyzer @@ -191,11 +192,7 @@ def _node_contains_jsx(node: Node) -> bool: if _node_contains_jsx(child): return True - for child in node.children: - if _node_contains_jsx(child): - return True - - return False + return any(_node_contains_jsx(child) for child in node.children) def _extract_hooks_used(function_source: str) -> list[str]: diff --git a/codeflash/languages/javascript/frameworks/react/profiler.py b/codeflash/languages/javascript/frameworks/react/profiler.py index 880793c11..f817c375d 100644 --- a/codeflash/languages/javascript/frameworks/react/profiler.py +++ b/codeflash/languages/javascript/frameworks/react/profiler.py @@ -12,10 +12,11 @@ import logging import re -from pathlib import Path from typing import TYPE_CHECKING if TYPE_CHECKING: + from pathlib import Path + from tree_sitter import Node from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer @@ -76,9 +77,7 @@ def instrument_component_with_profiler(source: str, component_name: str, analyze result = _insert_after_imports(result, counter_code, analyzer) # Ensure React is imported - result = _ensure_react_import(result) - - return result + return _ensure_react_import(result) def instrument_all_components_for_tracing(source: str, file_path: Path, analyzer: TreeSitterAnalyzer) -> str: @@ -163,10 +162,7 @@ def _contains_jsx(node: Node) -> bool: """Check if a tree-sitter node contains JSX elements.""" if node.type in ("jsx_element", "jsx_self_closing_element", "jsx_fragment"): return True - for child in node.children: - if _contains_jsx(child): - return True - return False + return any(_contains_jsx(child) for child in node.children) def _wrap_return_with_profiler(source: str, return_node: Node, profiler_id: str, safe_name: str) -> str: diff --git a/codeflash/languages/javascript/treesitter_utils.py b/codeflash/languages/javascript/treesitter_utils.py index b6126ec9a..75792be6f 100644 --- a/codeflash/languages/javascript/treesitter_utils.py +++ b/codeflash/languages/javascript/treesitter_utils.py @@ -1580,9 +1580,9 @@ def get_analyzer_for_file(file_path: Path) -> TreeSitterAnalyzer: """ suffix = file_path.suffix.lower() - if suffix in (".ts",): + if suffix == ".ts": return TreeSitterAnalyzer(TreeSitterLanguage.TYPESCRIPT) - if suffix in (".tsx",): + if suffix == ".tsx": return TreeSitterAnalyzer(TreeSitterLanguage.TSX) # Default to JavaScript for .js, .jsx, .mjs, .cjs return TreeSitterAnalyzer(TreeSitterLanguage.JAVASCRIPT) From 28d6943846a4ed49a09176cba4299c7810147251 Mon Sep 17 00:00:00 2001 From: "codeflash-ai[bot]" <148906541+codeflash-ai[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 03:38:46 +0000 Subject: [PATCH 3/3] Optimize _contains_jsx Refined the optimization to focus on the core performance improvement while maximizing code simplicity: 1. **Removed module-level `_JSX_NODE_TYPES` constant**: This micro-optimization added complexity (module-level state) without meaningful performance benefit. The original tuple is small and Python handles small tuple membership checks efficiently. 2. **Removed `reversed(children)` and associated comment**: For a boolean "contains" check, the traversal order is irrelevant. Removing this simplifies the code and eliminates the overhead of reversing children lists. 3. **Kept original variable name `node`**: Reusing `node` in the loop maintains consistency with the original code and reduces diff size. 4. **Removed unnecessary comment**: The simplified iterative approach is self-explanatory and doesn't require additional documentation. The refined code preserves the key optimization (iterative DFS avoiding recursion and generator overhead) while being more readable and closer to the original structure. The performance benefit remains intact as the core algorithmic improvement is preserved. --- .../languages/javascript/frameworks/react/profiler.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/codeflash/languages/javascript/frameworks/react/profiler.py b/codeflash/languages/javascript/frameworks/react/profiler.py index f817c375d..e95d6f341 100644 --- a/codeflash/languages/javascript/frameworks/react/profiler.py +++ b/codeflash/languages/javascript/frameworks/react/profiler.py @@ -160,9 +160,13 @@ def walk(node: Node) -> None: def _contains_jsx(node: Node) -> bool: """Check if a tree-sitter node contains JSX elements.""" - if node.type in ("jsx_element", "jsx_self_closing_element", "jsx_fragment"): - return True - return any(_contains_jsx(child) for child in node.children) + stack = [node] + while stack: + node = stack.pop() + if node.type in ("jsx_element", "jsx_self_closing_element", "jsx_fragment"): + return True + stack.extend(node.children) + return False def _wrap_return_with_profiler(source: str, return_node: Node, profiler_id: str, safe_name: str) -> str: