From b8597b2e85a2a8033a042531aac6b0d89fbc10ce Mon Sep 17 00:00:00 2001 From: Sarthak Agarwal Date: Wed, 11 Feb 2026 02:04:42 +0530 Subject: [PATCH 1/3] wrapped functions default export support --- codeflash/languages/treesitter_utils.py | 45 ++++++ tests/test_languages/test_treesitter_utils.py | 128 ++++++++++++++++++ 2 files changed, 173 insertions(+) diff --git a/codeflash/languages/treesitter_utils.py b/codeflash/languages/treesitter_utils.py index f4b7ead43..8493aaada 100644 --- a/codeflash/languages/treesitter_utils.py +++ b/codeflash/languages/treesitter_utils.py @@ -94,6 +94,9 @@ class ExportInfo: reexport_source: str | None # Module path for re-exports start_line: int end_line: int + # Functions passed as arguments to wrapper calls in default exports + # e.g., export default curry(traverseEntity) -> ["traverseEntity"] + wrapped_default_args: list[str] | None = None @dataclass @@ -707,6 +710,7 @@ def _extract_export_info(self, node: Node, source_bytes: bytes) -> ExportInfo | default_export: str | None = None is_reexport = False reexport_source: str | None = None + wrapped_default_args: list[str] | None = None # Check for re-export source (export { x } from './other') source_node = node.child_by_field_name("source") @@ -726,6 +730,12 @@ def _extract_export_info(self, node: Node, source_bytes: bytes) -> ExportInfo | default_export = self.get_node_text(sibling, source_bytes) elif sibling.type in ("arrow_function", "function_expression", "object", "array"): default_export = "default" + elif sibling.type == "call_expression": + # Handle wrapped exports: export default curry(traverseEntity) + # The default export is the result of the call, but we track + # the wrapped function names for export checking + default_export = "default" + wrapped_default_args = self._extract_call_expression_identifiers(sibling, source_bytes) break # Handle named exports: export { a, b as c } @@ -773,8 +783,37 @@ def _extract_export_info(self, node: Node, source_bytes: bytes) -> ExportInfo | reexport_source=reexport_source, start_line=node.start_point[0] + 1, end_line=node.end_point[0] + 1, + wrapped_default_args=wrapped_default_args, ) + def _extract_call_expression_identifiers(self, node: Node, source_bytes: bytes) -> list[str]: + """Extract identifier names from arguments of a call expression. + + For patterns like curry(traverseEntity) or compose(fn1, fn2), this extracts + the function names passed as arguments: ["traverseEntity"] or ["fn1", "fn2"]. + + Args: + node: A call_expression node. + source_bytes: The source code as bytes. + + Returns: + List of identifier names found in the call arguments. + + """ + identifiers: list[str] = [] + + # Get the arguments node + args_node = node.child_by_field_name("arguments") + if args_node: + for child in args_node.children: + if child.type == "identifier": + identifiers.append(self.get_node_text(child, source_bytes)) + # Also handle nested call expressions: compose(curry(fn)) + elif child.type == "call_expression": + identifiers.extend(self._extract_call_expression_identifiers(child, source_bytes)) + + return identifiers + def _extract_commonjs_export(self, node: Node, source_bytes: bytes) -> ExportInfo | None: """Extract export information from CommonJS module.exports or exports.* patterns. @@ -876,6 +915,7 @@ def is_function_exported( """Check if a function is exported and get its export name. For class methods, also checks if the containing class is exported. + Also handles wrapped exports like: export default curry(traverseEntity) Args: source: The source code to analyze. @@ -901,6 +941,11 @@ def is_function_exported( if name == function_name: return (True, alias if alias else name) + # Check wrapped default exports: export default curry(traverseEntity) + # The function is exported via wrapper, so it's accessible as "default" + if export.wrapped_default_args and function_name in export.wrapped_default_args: + return (True, "default") + # For class methods, check if the containing class is exported if class_name: for export in exports: diff --git a/tests/test_languages/test_treesitter_utils.py b/tests/test_languages/test_treesitter_utils.py index 2784facb0..72c56a5b7 100644 --- a/tests/test_languages/test_treesitter_utils.py +++ b/tests/test_languages/test_treesitter_utils.py @@ -693,3 +693,131 @@ def test_non_exported_const_not_exported(self, ts_analyzer): is_public_exported, name = ts_analyzer.is_function_exported(code, "publicFunc") assert is_public_exported is True assert name == "publicFunc" + + +class TestWrappedDefaultExports: + """Tests for wrapped default export pattern - Issue #9. + + Handles patterns like: + - export default curry(traverseEntity) + - export default compose(fn1, fn2) + - export default wrapper(myFunc) + + These must be correctly recognized so the wrapped function is exportable. + """ + + @pytest.fixture + def ts_analyzer(self): + """Create a TypeScript analyzer.""" + return TreeSitterAnalyzer(TreeSitterLanguage.TYPESCRIPT) + + def test_curry_wrapped_export(self, ts_analyzer): + """Test export default curry(fn) pattern.""" + code = """import { curry } from 'lodash/fp'; + +const traverseEntity = async (visitor, options, entity) => { + return entity; +}; + +export default curry(traverseEntity);""" + + # Check exports parsing + exports = ts_analyzer.find_exports(code) + assert len(exports) == 1 + assert exports[0].default_export == "default" + assert exports[0].wrapped_default_args == ["traverseEntity"] + + # Check is_function_exported + is_exported, export_name = ts_analyzer.is_function_exported(code, "traverseEntity") + assert is_exported is True + assert export_name == "default" + + def test_compose_wrapped_export(self, ts_analyzer): + """Test export default compose(fn1, fn2) pattern with multiple args.""" + code = """import { compose } from 'lodash/fp'; + +function validateInput(data) { return data; } +function processData(data) { return data; } + +export default compose(validateInput, processData);""" + + exports = ts_analyzer.find_exports(code) + assert len(exports) == 1 + assert exports[0].wrapped_default_args == ["validateInput", "processData"] + + # Both functions should be recognized as exported + is_exported1, _ = ts_analyzer.is_function_exported(code, "validateInput") + is_exported2, _ = ts_analyzer.is_function_exported(code, "processData") + assert is_exported1 is True + assert is_exported2 is True + + def test_nested_wrapper_export(self, ts_analyzer): + """Test nested wrapper: export default compose(curry(fn)).""" + code = """export default compose(curry(myFunc));""" + + exports = ts_analyzer.find_exports(code) + assert len(exports) == 1 + assert "myFunc" in exports[0].wrapped_default_args + + is_exported, _ = ts_analyzer.is_function_exported(code, "myFunc") + assert is_exported is True + + def test_generic_wrapper_export(self, ts_analyzer): + """Test generic wrapper function.""" + code = """const myFunction = (x: number) => x * 2; + +export default someWrapper(myFunction);""" + + is_exported, export_name = ts_analyzer.is_function_exported(code, "myFunction") + assert is_exported is True + assert export_name == "default" + + def test_non_wrapped_function_not_exported(self, ts_analyzer): + """Test that functions not in the wrapper call are not exported.""" + code = """const helper = (x: number) => x + 1; +const main = (x: number) => helper(x) * 2; + +export default curry(main);""" + + # main is wrapped, so it's exported + is_main_exported, _ = ts_analyzer.is_function_exported(code, "main") + assert is_main_exported is True + + # helper is NOT in the wrapper call, so not exported + is_helper_exported, _ = ts_analyzer.is_function_exported(code, "helper") + assert is_helper_exported is False + + def test_direct_default_export_still_works(self, ts_analyzer): + """Test that direct default exports still work.""" + code = """function myFunc() { return 1; } +export default myFunc;""" + + is_exported, export_name = ts_analyzer.is_function_exported(code, "myFunc") + assert is_exported is True + assert export_name == "default" + + def test_strapi_traverse_entity_pattern(self, ts_analyzer): + """Test the exact strapi pattern that was failing.""" + code = """import { curry } from 'lodash/fp'; + +const traverseEntity = async (visitor: Visitor, options: TraverseOptions, entity: Data) => { + const { path = { raw: null }, schema, getModel } = options; + // ... implementation + return copy; +}; + +const createVisitorUtils = ({ data }: { data: Data }) => ({ + remove(key: string) { delete data[key]; }, + set(key: string, value: Data) { data[key] = value; }, +}); + +export default curry(traverseEntity);""" + + # traverseEntity should be recognized as exported + is_exported, export_name = ts_analyzer.is_function_exported(code, "traverseEntity") + assert is_exported is True + assert export_name == "default" + + # createVisitorUtils is NOT wrapped, so not exported via default + is_utils_exported, _ = ts_analyzer.is_function_exported(code, "createVisitorUtils") + assert is_utils_exported is False From fa56eb7abee6c1e490674e8946f380f7eeb1dbd9 Mon Sep 17 00:00:00 2001 From: Sarthak Agarwal Date: Wed, 11 Feb 2026 02:05:54 +0530 Subject: [PATCH 2/3] refactor --- MULTI_LANGUAGE_ARCHITECTURE.md | 4 +- codeflash/code_utils/code_extractor.py | 2 +- codeflash/code_utils/code_replacer.py | 4 +- .../code_utils/normalizers/javascript.py | 2 +- codeflash/discovery/functions_to_optimize.py | 2 +- .../languages/javascript/find_references.py | 6 +-- .../languages/javascript/import_resolver.py | 6 +-- codeflash/languages/javascript/instrument.py | 2 +- .../languages/javascript/line_profiler.py | 2 +- codeflash/languages/javascript/support.py | 4 +- .../treesitter.py} | 0 tests/test_languages/test_import_resolver.py | 10 ++--- .../test_languages/test_javascript_support.py | 2 +- .../test_javascript_test_discovery.py | 38 +++++++++---------- tests/test_languages/test_treesitter_utils.py | 2 +- 15 files changed, 43 insertions(+), 43 deletions(-) rename codeflash/languages/{treesitter_utils.py => javascript/treesitter.py} (100%) diff --git a/MULTI_LANGUAGE_ARCHITECTURE.md b/MULTI_LANGUAGE_ARCHITECTURE.md index e3cbaf4bb..5983afade 100644 --- a/MULTI_LANGUAGE_ARCHITECTURE.md +++ b/MULTI_LANGUAGE_ARCHITECTURE.md @@ -386,7 +386,7 @@ class JavaScriptTransformer: from pathlib import Path from codeflash.languages.base import LanguageSupport, FunctionInfo, CodeContext -from codeflash.languages.treesitter_utils import TreeSitterAnalyzer +from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer from codeflash.languages.javascript.transformer import JavaScriptTransformer class JavaScriptSupport(LanguageSupport): @@ -523,7 +523,7 @@ class JavaScriptSupport(LanguageSupport): # codeflash/languages/javascript/test_discovery.py from pathlib import Path -from codeflash.languages.treesitter_utils import TreeSitterAnalyzer +from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer class JestTestDiscovery: """Static analysis-based test discovery for Jest.""" diff --git a/codeflash/code_utils/code_extractor.py b/codeflash/code_utils/code_extractor.py index e2b9a9d52..c4434c3ae 100644 --- a/codeflash/code_utils/code_extractor.py +++ b/codeflash/code_utils/code_extractor.py @@ -1772,7 +1772,7 @@ def _extract_calling_function_js(source_code: str, function_name: str, ref_line: """ try: - from codeflash.languages.treesitter_utils import TreeSitterAnalyzer, TreeSitterLanguage + from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage # Try TypeScript first, fall back to JavaScript for lang in [TreeSitterLanguage.TYPESCRIPT, TreeSitterLanguage.TSX, TreeSitterLanguage.JAVASCRIPT]: diff --git a/codeflash/code_utils/code_replacer.py b/codeflash/code_utils/code_replacer.py index e543d184d..d4478207c 100644 --- a/codeflash/code_utils/code_replacer.py +++ b/codeflash/code_utils/code_replacer.py @@ -26,7 +26,7 @@ from codeflash.discovery.functions_to_optimize import FunctionToOptimize from codeflash.languages.base import Language, LanguageSupport - from codeflash.languages.treesitter_utils import TreeSitterAnalyzer + from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer from codeflash.models.models import CodeOptimizationContext, CodeStringsMarkdown, OptimizedCandidate, ValidCode ASTNodeT = TypeVar("ASTNodeT", bound=ast.AST) @@ -640,7 +640,7 @@ def _add_global_declarations_for_language( return original_source try: - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(module_abspath) diff --git a/codeflash/code_utils/normalizers/javascript.py b/codeflash/code_utils/normalizers/javascript.py index e3a4faae0..fa61b19a7 100644 --- a/codeflash/code_utils/normalizers/javascript.py +++ b/codeflash/code_utils/normalizers/javascript.py @@ -233,7 +233,7 @@ def normalize(self, code: str) -> str: """ try: - from codeflash.languages.treesitter_utils import TreeSitterAnalyzer, TreeSitterLanguage + from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage lang_map = {"javascript": TreeSitterLanguage.JAVASCRIPT, "typescript": TreeSitterLanguage.TYPESCRIPT} lang = lang_map.get(self._get_tree_sitter_language(), TreeSitterLanguage.JAVASCRIPT) diff --git a/codeflash/discovery/functions_to_optimize.py b/codeflash/discovery/functions_to_optimize.py index 740528c0c..29bea8761 100644 --- a/codeflash/discovery/functions_to_optimize.py +++ b/codeflash/discovery/functions_to_optimize.py @@ -201,7 +201,7 @@ def _is_js_ts_function_exported(file_path: Path, function_name: str) -> tuple[bo Tuple of (is_exported, export_name). export_name may be 'default' for default exports. """ - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file try: source = file_path.read_text(encoding="utf-8") diff --git a/codeflash/languages/javascript/find_references.py b/codeflash/languages/javascript/find_references.py index 16b93cfca..a9921e2e5 100644 --- a/codeflash/languages/javascript/find_references.py +++ b/codeflash/languages/javascript/find_references.py @@ -23,7 +23,7 @@ from tree_sitter import Node from codeflash.discovery.functions_to_optimize import FunctionToOptimize - from codeflash.languages.treesitter_utils import ImportInfo, TreeSitterAnalyzer + from codeflash.languages.javascript.treesitter import ImportInfo, TreeSitterAnalyzer logger = logging.getLogger(__name__) @@ -112,7 +112,7 @@ def find_references( List of Reference objects describing each call site. """ - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file function_name = function_to_optimize.function_name source_file = function_to_optimize.file_path @@ -719,7 +719,7 @@ def _find_reexports_direct( continue # Create a fake ImportInfo to resolve the re-export source - from codeflash.languages.treesitter_utils import ImportInfo + from codeflash.languages.javascript.treesitter import ImportInfo fake_import = ImportInfo( module_path=exp.reexport_source, diff --git a/codeflash/languages/javascript/import_resolver.py b/codeflash/languages/javascript/import_resolver.py index 45ae530d5..885c709e3 100644 --- a/codeflash/languages/javascript/import_resolver.py +++ b/codeflash/languages/javascript/import_resolver.py @@ -14,7 +14,7 @@ if TYPE_CHECKING: from codeflash.discovery.functions_to_optimize import FunctionToOptimize from codeflash.languages.base import HelperFunction - from codeflash.languages.treesitter_utils import ImportInfo, TreeSitterAnalyzer + from codeflash.languages.javascript.treesitter import ImportInfo, TreeSitterAnalyzer logger = logging.getLogger(__name__) @@ -486,7 +486,7 @@ def _extract_helper_from_file( """ from codeflash.languages.base import HelperFunction - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file try: source = file_path.read_text(encoding="utf-8") @@ -559,7 +559,7 @@ def _find_helpers_recursive( """ from codeflash.discovery.functions_to_optimize import FunctionToOptimize from codeflash.languages.registry import get_language_support - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file if context.current_depth >= context.max_depth: return {} diff --git a/codeflash/languages/javascript/instrument.py b/codeflash/languages/javascript/instrument.py index 028209326..938c160aa 100644 --- a/codeflash/languages/javascript/instrument.py +++ b/codeflash/languages/javascript/instrument.py @@ -792,7 +792,7 @@ def validate_and_fix_import_style(test_code: str, source_file_path: Path, functi Fixed test code with correct import style. """ - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file # Read source file to determine export style try: diff --git a/codeflash/languages/javascript/line_profiler.py b/codeflash/languages/javascript/line_profiler.py index 57f046d4a..81b38983c 100644 --- a/codeflash/languages/javascript/line_profiler.py +++ b/codeflash/languages/javascript/line_profiler.py @@ -11,7 +11,7 @@ import logging from typing import TYPE_CHECKING -from codeflash.languages.treesitter_utils import get_analyzer_for_file +from codeflash.languages.javascript.treesitter import get_analyzer_for_file if TYPE_CHECKING: from pathlib import Path diff --git a/codeflash/languages/javascript/support.py b/codeflash/languages/javascript/support.py index 0a12f48a7..16dcac14f 100644 --- a/codeflash/languages/javascript/support.py +++ b/codeflash/languages/javascript/support.py @@ -15,14 +15,14 @@ from codeflash.discovery.functions_to_optimize import FunctionToOptimize from codeflash.languages.base import CodeContext, FunctionFilterCriteria, HelperFunction, Language, TestInfo, TestResult from codeflash.languages.registry import register_language -from codeflash.languages.treesitter_utils import TreeSitterAnalyzer, TreeSitterLanguage, get_analyzer_for_file +from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage, get_analyzer_for_file from codeflash.models.models import FunctionParent if TYPE_CHECKING: from collections.abc import Sequence from codeflash.languages.base import ReferenceInfo - from codeflash.languages.treesitter_utils import TypeDefinition + from codeflash.languages.javascript.treesitter import TypeDefinition logger = logging.getLogger(__name__) diff --git a/codeflash/languages/treesitter_utils.py b/codeflash/languages/javascript/treesitter.py similarity index 100% rename from codeflash/languages/treesitter_utils.py rename to codeflash/languages/javascript/treesitter.py diff --git a/tests/test_languages/test_import_resolver.py b/tests/test_languages/test_import_resolver.py index 0f50a8833..5b27179c5 100644 --- a/tests/test_languages/test_import_resolver.py +++ b/tests/test_languages/test_import_resolver.py @@ -8,7 +8,7 @@ import pytest from codeflash.languages.javascript.import_resolver import HelperSearchContext, ImportResolver, MultiFileHelperFinder -from codeflash.languages.treesitter_utils import ImportInfo +from codeflash.languages.javascript.treesitter import ImportInfo class TestImportResolver: @@ -286,7 +286,7 @@ class TestExportInfo: @pytest.fixture def js_analyzer(self): """Create a JavaScript analyzer.""" - from codeflash.languages.treesitter_utils import TreeSitterAnalyzer, TreeSitterLanguage + from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage return TreeSitterAnalyzer(TreeSitterLanguage.JAVASCRIPT) @@ -388,7 +388,7 @@ class TestCommonJSRequire: @pytest.fixture def js_analyzer(self): """Create a JavaScript analyzer.""" - from codeflash.languages.treesitter_utils import TreeSitterAnalyzer, TreeSitterLanguage + from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage return TreeSitterAnalyzer(TreeSitterLanguage.JAVASCRIPT) @@ -470,14 +470,14 @@ class TestCommonJSExports: @pytest.fixture def js_analyzer(self): """Create a JavaScript analyzer.""" - from codeflash.languages.treesitter_utils import TreeSitterAnalyzer, TreeSitterLanguage + from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage return TreeSitterAnalyzer(TreeSitterLanguage.JAVASCRIPT) @pytest.fixture def ts_analyzer(self): """Create a TypeScript analyzer.""" - from codeflash.languages.treesitter_utils import TreeSitterAnalyzer, TreeSitterLanguage + from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage return TreeSitterAnalyzer(TreeSitterLanguage.TYPESCRIPT) diff --git a/tests/test_languages/test_javascript_support.py b/tests/test_languages/test_javascript_support.py index fc7343e48..7a6868a66 100644 --- a/tests/test_languages/test_javascript_support.py +++ b/tests/test_languages/test_javascript_support.py @@ -654,7 +654,7 @@ def test_find_jest_tests(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) diff --git a/tests/test_languages/test_javascript_test_discovery.py b/tests/test_languages/test_javascript_test_discovery.py index 9166b589e..473bd330e 100644 --- a/tests/test_languages/test_javascript_test_discovery.py +++ b/tests/test_languages/test_javascript_test_discovery.py @@ -627,7 +627,7 @@ def test_find_basic_tests(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -652,7 +652,7 @@ def test_find_describe_blocks(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -676,7 +676,7 @@ def test_find_nested_describe_blocks(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -700,7 +700,7 @@ def test_find_tests_with_skip(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -721,7 +721,7 @@ def test_find_tests_with_only(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -739,7 +739,7 @@ def test_find_tests_with_single_quotes(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -758,7 +758,7 @@ def test_find_tests_with_double_quotes(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -774,7 +774,7 @@ def test_find_tests_empty_file(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1020,7 +1020,7 @@ def test_unicode_in_test_names(self, js_support): file_path = Path(f.name) source = file_path.read_text(encoding="utf-8") - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1048,7 +1048,7 @@ def test_find_test_each_array(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1074,7 +1074,7 @@ def test_find_describe_each(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1099,7 +1099,7 @@ def test_find_it_each(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1457,7 +1457,7 @@ def test_dynamic_test_names(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1485,7 +1485,7 @@ def test_conditional_tests(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1509,7 +1509,7 @@ def test_test_with_timeout(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1532,7 +1532,7 @@ def test_todo_tests(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1555,7 +1555,7 @@ def test_concurrent_tests(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1654,7 +1654,7 @@ def test_mocha_bdd_style(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) @@ -1685,7 +1685,7 @@ def test_context_block(self, js_support): file_path = Path(f.name) source = file_path.read_text() - from codeflash.languages.treesitter_utils import get_analyzer_for_file + from codeflash.languages.javascript.treesitter import get_analyzer_for_file analyzer = get_analyzer_for_file(file_path) test_names = js_support._find_jest_tests(source, analyzer) diff --git a/tests/test_languages/test_treesitter_utils.py b/tests/test_languages/test_treesitter_utils.py index 72c56a5b7..15dd1219b 100644 --- a/tests/test_languages/test_treesitter_utils.py +++ b/tests/test_languages/test_treesitter_utils.py @@ -8,7 +8,7 @@ import pytest -from codeflash.languages.treesitter_utils import TreeSitterAnalyzer, TreeSitterLanguage, get_analyzer_for_file +from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage, get_analyzer_for_file class TestTreeSitterLanguage: From 78ce6e6f2efc569c364ef666abb18abdd358fe8e Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 20:42:54 +0000 Subject: [PATCH 3/3] style: auto-fix linting issues Co-Authored-By: Claude Opus 4.6 --- codeflash/languages/javascript/find_references.py | 6 +++--- codeflash/languages/javascript/import_resolver.py | 2 +- codeflash/languages/javascript/support.py | 2 +- codeflash/languages/javascript/treesitter.py | 4 ++-- codeflash/version.py | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/codeflash/languages/javascript/find_references.py b/codeflash/languages/javascript/find_references.py index a9921e2e5..ed6e30636 100644 --- a/codeflash/languages/javascript/find_references.py +++ b/codeflash/languages/javascript/find_references.py @@ -168,7 +168,7 @@ def find_references( if import_info: # Found an import - mark as visited and search for calls context.visited_files.add(file_path) - import_name, original_import = import_info + import_name, _original_import = import_info file_refs = self._find_references_in_file( file_path, file_code, function_name, import_name, file_analyzer, include_self=True ) @@ -213,7 +213,7 @@ def find_references( trigger_check = True if import_info: context.visited_files.add(file_path) - import_name, original_import = import_info + import_name, _original_import = import_info file_refs = self._find_references_in_file( file_path, file_code, reexport_name, import_name, file_analyzer, include_self=True ) @@ -404,7 +404,7 @@ def _find_identifier_references( name_node = node.child_by_field_name("name") if name_node: new_current_function = source_bytes[name_node.start_byte : name_node.end_byte].decode("utf8") - elif node.type in ("variable_declarator",): + elif node.type == "variable_declarator": # Arrow function or function expression assigned to variable name_node = node.child_by_field_name("name") value_node = node.child_by_field_name("value") diff --git a/codeflash/languages/javascript/import_resolver.py b/codeflash/languages/javascript/import_resolver.py index 885c709e3..8f5dbe8ca 100644 --- a/codeflash/languages/javascript/import_resolver.py +++ b/codeflash/languages/javascript/import_resolver.py @@ -558,8 +558,8 @@ def _find_helpers_recursive( """ from codeflash.discovery.functions_to_optimize import FunctionToOptimize - from codeflash.languages.registry import get_language_support from codeflash.languages.javascript.treesitter import get_analyzer_for_file + from codeflash.languages.registry import get_language_support if context.current_depth >= context.max_depth: return {} diff --git a/codeflash/languages/javascript/support.py b/codeflash/languages/javascript/support.py index 16dcac14f..d32cce001 100644 --- a/codeflash/languages/javascript/support.py +++ b/codeflash/languages/javascript/support.py @@ -14,8 +14,8 @@ from codeflash.discovery.functions_to_optimize import FunctionToOptimize from codeflash.languages.base import CodeContext, FunctionFilterCriteria, HelperFunction, Language, TestInfo, TestResult -from codeflash.languages.registry import register_language from codeflash.languages.javascript.treesitter import TreeSitterAnalyzer, TreeSitterLanguage, get_analyzer_for_file +from codeflash.languages.registry import register_language from codeflash.models.models import FunctionParent if TYPE_CHECKING: diff --git a/codeflash/languages/javascript/treesitter.py b/codeflash/languages/javascript/treesitter.py index 8493aaada..650d899a5 100644 --- a/codeflash/languages/javascript/treesitter.py +++ b/codeflash/languages/javascript/treesitter.py @@ -1625,9 +1625,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) diff --git a/codeflash/version.py b/codeflash/version.py index 6225467e3..6d60ab0c2 100644 --- a/codeflash/version.py +++ b/codeflash/version.py @@ -1,2 +1,2 @@ # These version placeholders will be replaced by uv-dynamic-versioning during build. -__version__ = "0.20.0" +__version__ = "0.20.0.post510.dev0+b8932209"