For JavaScript projects, generated tests are placed near the source file
(e.g., code_to_optimize/js/.../tests/codeflash-generated/) rather than
under tests_project_rootdir. This caused module_name_from_file_path to
crash with ValueError. Fall back to project_root_path when the test path
isn't under tests_project_rootdir.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The early `parsed_dst_module = None` assignment broke mypy's type narrowing.
Add explicit `else: parsed_dst_module = dst_module_code` so mypy sees the
variable is always a `cst.Module` before the `.visit()` call.
Co-authored-by: Kevin Turcios <undefined@users.noreply.github.com>
time.time_ns() has ~15ms resolution on Windows, causing fast benchmark
functions to record 0 ns elapsed time and fail timing assertions.
time.perf_counter_ns() provides ~100ns resolution on all platforms.
Co-authored-by: Aseem Saxena <aseembits93@users.noreply.github.com>
- Remove silent .lstrip("\n") on fallback for cst.Module input (restores original behavior)
- Replace `parsed_dst_module is None` with `isinstance(dst_module_code, str)` for correct mypy narrowing
- Change get_jedi_project return type from object to Any for accuracy
Co-authored-by: Kevin Turcios <KRRT7@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
get_git_diff() hardcoded `.py` as the only valid file extension, causing
the auto-detect flow (no --file flag) to return 0 functions for Java,
JavaScript, and TypeScript projects. This broke the Claude Code plugin
integration where the hook runs `codeflash --subagent` without --file.
Now uses current_language_support().file_extensions to filter by the
active language's extensions dynamically.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Covers setup_test_config symlinking node_modules from original repo
to worktree, including edge cases (no worktree, missing node_modules,
already existing node_modules).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace with
in
_maybe_strip_docstring — the | syntax for runtime isinstance is Python 3.10+
only and caused TypeError on 3.9
- Strip leading newlines from cst.Module.code in add_needed_imports_from_module
fallback path so early-exit returns are consistent with the normal
transformed_module.code.lstrip("\n") path, fixing extra blank lines after
file headers in read_writable_code.flat output
Co-Authored-By: Oz <oz-agent@warp.dev>
The generator expression yielded `isinstance(stmt, ...)` where `stmt` was
already filtered to be `cst.SimpleStatementLine`, so it always returned False.
This caused add_needed_imports_from_module to always skip adding imports,
breaking 11 tests in test_code_context_extractor.py.
Co-authored-by: Kevin Turcios <undefined@users.noreply.github.com>
Replace three `from X import support as _` patterns with a loop using
`importlib.import_module()`, eliminating the duplicate name binding.
Co-authored-by: Kevin Turcios <KRRT7@users.noreply.github.com>
The function was removed in the dead code cleanup but the test file still
imported it and had a TestCreatePyprojectToml class, causing ImportError.
Co-authored-by: Kevin Turcios <undefined@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Function now lives alongside the console/logger it depends on.
Updated all 8 callers to import from cli_cmds.console instead.
Co-Authored-By: Oz <oz-agent@warp.dev>
inquirer_wrapper, inquirer_wrapper_path, split_string_to_cli_width,
and split_string_to_fit_width were replaced by direct inquirer usage
with CodeflashTheme and rich.prompt.Confirm. Only apologize_and_exit
remains.
Co-Authored-By: Oz <oz-agent@warp.dev>
The optimization added early-exit logic to `add_needed_imports_from_module` that checks whether the source module contains any module-level imports before invoking the heavyweight `GatherImportsVisitor` and downstream import-merging machinery. In the common case where a pruned module has no imports (or only nested ones inside functions), line profiling showed the gatherer and two `AddImportsVisitor`/`RemoveImportsVisitor` transforms consumed 36% of original runtime; the early exit skips all three, falling back to the destination code immediately. A second early exit after gathering verifies the visitor actually collected imports, avoiding redundant CST transformations when the source is import-free. Combined, these checks eliminate ~99% of the work when imports are absent, yielding an 18222% speedup with no semantic change because the fallback path always returned the correct destination code.
Port valuable improvements from #1846 that remain applicable after #1660:
- Cache jedi.Project instances via @cache to avoid recreating across 5 call sites
- Fix unguarded relative_to() in get_code_optimization_context (Windows 8.3 paths)
- Pre-group references by parent function in get_function_sources_from_jedi for O(1) lookup
- Batch TestsCache writes with flush() + executemany instead of per-row commit
- Gracefully disable cache writes on sqlite3.OperationalError
- Build functions_to_optimize_by_name dict for O(1) fallback lookup in process_test_files
- Derive all_defs from all_names via is_definition() to save a redundant Jedi call
- Fix duplicate type annotation for test_count_cache in optimizer.py
- Replace ast.walk() with stack-based traversal in _find_class_node_by_name (21x speedup)
- Use list instead of deque in CallGraph.ancestors (34% speedup, order doesn't matter for set result)
The optimization replaced recursive calls in `_get_expr_name` with an iterative loop that walks attribute chains once, collecting parts into a list and reversing them only at the end, eliminating function-call overhead that dominated 46% of original runtime (line profiler shows recursive calls at 1154 ns/hit vs. the new loop iterations at ~300 ns/hit). Additionally, `_expr_matches_name` now precomputes `"." + suffix` once instead of building it twice per invocation via f-strings, cutting redundant string allocations. The net 26% runtime improvement comes primarily from avoiding Python's recursion stack and reducing temporary object creation in the hot path, with all tests passing and only minor per-test slowdowns (typically 10–25%) offset by dramatic wins on deep attribute chains (up to 393% faster for 100-level nesting).
Expanded bug fix workflow to explicit 5-step sequence with subagent delegation, aligned type annotation rule with codebase conventions, simplified verification rule to reference prek, and expanded git/PR guidelines.
Runtime annotations in PR descriptions were broken in two ways:
1. add_runtime_comments() ignored class/method prefixes in keys, causing
annotations from unrelated test classes to leak across files and sum
incorrectly at the same line number. Now filters by class names found
in each test source file.
2. Test functions were removed before annotations were added, shifting
line numbers so annotations landed on wrong lines. Swapped ordering
so annotations are applied first, then function removal carries them
along correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The optimization replaced a large multi-type `isinstance()` check (13 AST node types constructed into a tuple on every iteration) with a single `hasattr(node, "body")` test, then conditionally checked for `orelse`, `finalbody`, and `handlers` only when `body` exists. Line profiler shows the original `isinstance` block consumed ~40% of runtime across 7327 calls, while the new `hasattr` checks are ~3× cheaper per call. The nested conditionals avoid calling `getattr` with default values when attributes are absent (e.g., `orelse` is missing in 85% of nodes), cutting wasted attribute lookups from four unconditional `getattr` calls to typically one or two `hasattr` checks plus direct accesses. Across 59 test runs processing ~7300 AST nodes each, this yields a 109% speedup with identical correctness.