Skip to content

Commit 3e72ebc

Browse files
committed
refactor: clean up code replacer and remove dead code
- Remove unreachable non-Python branch from replace_function_definitions_in_module - Move language-agnostic code replacer functions to languages/code_replacer.py - Simplify PythonFunctionOptimizer.get_code_optimization_context - Remove dead worktree code replacement functions (no callers)
1 parent 652ff87 commit 3e72ebc

5 files changed

Lines changed: 154 additions & 306 deletions

File tree

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
"""Language-agnostic code replacement utilities.
2+
3+
Used by non-Python language optimizers to replace function definitions
4+
via the LanguageSupport protocol.
5+
"""
6+
7+
from __future__ import annotations
8+
9+
from typing import TYPE_CHECKING
10+
11+
from codeflash.cli_cmds.console import logger
12+
13+
if TYPE_CHECKING:
14+
from pathlib import Path
15+
16+
from codeflash.discovery.functions_to_optimize import FunctionToOptimize
17+
from codeflash.languages.base import LanguageSupport
18+
from codeflash.models.models import CodeStringsMarkdown
19+
20+
21+
def get_optimized_code_for_module(relative_path: Path, optimized_code: CodeStringsMarkdown) -> str:
22+
file_to_code_context = optimized_code.file_to_path()
23+
module_optimized_code = file_to_code_context.get(str(relative_path))
24+
if module_optimized_code is None:
25+
# Fallback: if there's only one code block with None file path,
26+
# use it regardless of the expected path (the AI server doesn't always include file paths)
27+
if "None" in file_to_code_context and len(file_to_code_context) == 1:
28+
module_optimized_code = file_to_code_context["None"]
29+
logger.debug(f"Using code block with None file_path for {relative_path}")
30+
else:
31+
logger.warning(
32+
f"Optimized code not found for {relative_path} In the context\n-------\n{optimized_code}\n-------\n"
33+
"re-check your 'markdown code structure'"
34+
f"existing files are {file_to_code_context.keys()}"
35+
)
36+
module_optimized_code = ""
37+
return module_optimized_code
38+
39+
40+
def replace_function_definitions_for_language(
41+
function_names: list[str],
42+
optimized_code: CodeStringsMarkdown,
43+
module_abspath: Path,
44+
project_root_path: Path,
45+
lang_support: LanguageSupport,
46+
function_to_optimize: FunctionToOptimize | None = None,
47+
) -> bool:
48+
"""Replace function definitions using the LanguageSupport protocol.
49+
50+
Works for any language that implements LanguageSupport.replace_function
51+
and LanguageSupport.discover_functions_from_source.
52+
"""
53+
original_source_code: str = module_abspath.read_text(encoding="utf8")
54+
code_to_apply = get_optimized_code_for_module(module_abspath.relative_to(project_root_path), optimized_code)
55+
56+
original_source_code = lang_support.add_global_declarations(
57+
optimized_code=code_to_apply, original_source=original_source_code, module_abspath=module_abspath
58+
)
59+
60+
if (
61+
function_to_optimize
62+
and function_to_optimize.starting_line
63+
and function_to_optimize.ending_line
64+
and function_to_optimize.file_path == module_abspath
65+
):
66+
optimized_func = _extract_function_from_code(
67+
lang_support, code_to_apply, function_to_optimize.function_name, module_abspath
68+
)
69+
if optimized_func:
70+
new_code = lang_support.replace_function(original_source_code, function_to_optimize, optimized_func)
71+
else:
72+
new_code = lang_support.replace_function(original_source_code, function_to_optimize, code_to_apply)
73+
else:
74+
new_code = original_source_code
75+
modified = False
76+
77+
functions_to_replace = list(function_names)
78+
79+
for func_name in functions_to_replace:
80+
current_functions = lang_support.discover_functions_from_source(new_code, module_abspath)
81+
82+
func = None
83+
for f in current_functions:
84+
if func_name in (f.qualified_name, f.function_name):
85+
func = f
86+
break
87+
88+
if func is None:
89+
continue
90+
91+
optimized_func = _extract_function_from_code(
92+
lang_support, code_to_apply, func.function_name, module_abspath
93+
)
94+
if optimized_func:
95+
new_code = lang_support.replace_function(new_code, func, optimized_func)
96+
modified = True
97+
98+
if not modified:
99+
logger.warning(f"Could not find function {function_names} in {module_abspath}")
100+
return False
101+
102+
if original_source_code.strip() == new_code.strip():
103+
return False
104+
105+
module_abspath.write_text(new_code, encoding="utf8")
106+
return True
107+
108+
109+
def _extract_function_from_code(
110+
lang_support: LanguageSupport, source_code: str, function_name: str, file_path: Path | None = None
111+
) -> str | None:
112+
"""Extract a specific function's source code from a code string.
113+
114+
Includes JSDoc/docstring comments if present.
115+
"""
116+
try:
117+
functions = lang_support.discover_functions_from_source(source_code, file_path)
118+
for func in functions:
119+
if func.function_name == function_name:
120+
lines = source_code.splitlines(keepends=True)
121+
effective_start = func.doc_start_line or func.starting_line
122+
if effective_start and func.ending_line and effective_start <= len(lines):
123+
func_lines = lines[effective_start - 1 : func.ending_line]
124+
return "".join(func_lines)
125+
except Exception as e:
126+
logger.debug(f"Error extracting function {function_name}: {e}")
127+
128+
return None

codeflash/languages/javascript/function_optimizer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def replace_function_and_helpers_with_optimized_code(
212212
optimized_code: CodeStringsMarkdown,
213213
original_helper_code: dict[Path, str],
214214
) -> bool:
215-
from codeflash.languages.python.static_analysis.code_replacer import replace_function_definitions_for_language
215+
from codeflash.languages.code_replacer import replace_function_definitions_for_language
216216

217217
did_update = False
218218
read_writable_functions_by_file_path: dict[Path, set[str]] = defaultdict(set)
@@ -228,6 +228,7 @@ def replace_function_and_helpers_with_optimized_code(
228228
optimized_code=optimized_code,
229229
module_abspath=module_abspath,
230230
project_root_path=self.project_root,
231+
lang_support=self.language_support,
231232
function_to_optimize=self.function_to_optimize,
232233
)
233234
return did_update

codeflash/languages/python/function_optimizer.py

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
modify_autouse_fixture,
1919
)
2020
from codeflash.languages.python.static_analysis.line_profile_utils import add_decorator_imports, contains_jit_decorator
21-
from codeflash.models.models import CodeOptimizationContext, TestingMode, TestResults
21+
from codeflash.models.models import TestingMode, TestResults
2222
from codeflash.optimization.function_optimizer import FunctionOptimizer
2323
from codeflash.verification.parse_test_output import calculate_function_throughput_from_test_results
2424

@@ -29,6 +29,7 @@
2929
from codeflash.languages.base import Language
3030
from codeflash.models.function_types import FunctionParent
3131
from codeflash.models.models import (
32+
CodeOptimizationContext,
3233
CodeStringsMarkdown,
3334
ConcurrencyMetrics,
3435
CoverageData,
@@ -42,25 +43,14 @@ def get_code_optimization_context(self) -> Result[CodeOptimizationContext, str]:
4243
from codeflash.languages.python.context import code_context_extractor
4344

4445
try:
45-
new_code_ctx = code_context_extractor.get_code_optimization_context(
46-
self.function_to_optimize, self.project_root, call_graph=self.call_graph
46+
return Success(
47+
code_context_extractor.get_code_optimization_context(
48+
self.function_to_optimize, self.project_root, call_graph=self.call_graph
49+
)
4750
)
4851
except ValueError as e:
4952
return Failure(str(e))
5053

51-
return Success(
52-
CodeOptimizationContext(
53-
testgen_context=new_code_ctx.testgen_context,
54-
read_writable_code=new_code_ctx.read_writable_code,
55-
read_only_context_code=new_code_ctx.read_only_context_code,
56-
hashing_code_context=new_code_ctx.hashing_code_context,
57-
hashing_code_context_hash=new_code_ctx.hashing_code_context_hash,
58-
helper_functions=new_code_ctx.helper_functions,
59-
testgen_helper_fqns=new_code_ctx.testgen_helper_fqns,
60-
preexisting_objects=new_code_ctx.preexisting_objects,
61-
)
62-
)
63-
6454
def _resolve_function_ast(
6555
self, source_code: str, function_name: str, parents: list[FunctionParent]
6656
) -> ast.FunctionDef | ast.AsyncFunctionDef | None:

0 commit comments

Comments
 (0)