Skip to content

Commit 3bd0255

Browse files
fix: scope field extraction to target class to prevent cross-class injection
find_fields() was called without a class_name filter, causing fields from inner/anonymous classes to be injected into the outer target class. Now scoped to target_method.class_name using the existing filter parameter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3c38a80 commit 3bd0255

2 files changed

Lines changed: 79 additions & 2 deletions

File tree

codeflash/languages/java/replacement.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ def _parse_optimization_source(new_source: str, target_method_name: str, analyze
6969
if classes:
7070
# It's a class - extract components
7171
methods = analyzer.find_methods(new_source)
72-
fields = analyzer.find_fields(new_source)
7372

7473
# Find the target method and its index among all methods
7574
target_method = None
@@ -128,7 +127,11 @@ def _parse_optimization_source(new_source: str, target_method_name: str, analyze
128127
ctor_end = c.end_line
129128
modified_constructors.append("".join(ctor_lines[ctor_start:ctor_end]))
130129

131-
# Extract fields
130+
# Extract fields scoped to the target method's class only.
131+
# Without class filtering, fields from inner/anonymous classes would be
132+
# incorrectly injected into the outer target class.
133+
target_class_name = target_method.class_name if target_method else None
134+
fields = analyzer.find_fields(new_source, class_name=target_class_name)
132135
for f in fields:
133136
if f.source_text:
134137
new_fields.append(f.source_text)

tests/test_languages/test_java/test_replacement.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,3 +1929,77 @@ def test_anonymous_iterator_methods_not_hoisted_to_class(self, tmp_path, java_su
19291929
}
19301930
"""
19311931
assert new_code == expected_code
1932+
1933+
1934+
class TestFieldInjectionClassFiltering:
1935+
"""Tests that fields from inner/anonymous classes are not injected into the target class."""
1936+
1937+
def test_inner_class_fields_not_injected_into_outer(self, tmp_path, java_support):
1938+
"""Reproduces the Guava/Iterables.mergeSorted bug.
1939+
1940+
When the LLM generates an optimization that includes an inner class with
1941+
fields (e.g., generic type parameters), those fields must NOT be injected
1942+
into the outer class where the target method lives.
1943+
"""
1944+
from codeflash.discovery.functions_to_optimize import FunctionParent, FunctionToOptimize
1945+
1946+
java_file = tmp_path / "Outer.java"
1947+
original_code = """\
1948+
public class Outer {
1949+
private int count;
1950+
1951+
public int process(int x) {
1952+
return x + count;
1953+
}
1954+
}
1955+
"""
1956+
java_file.write_text(original_code, encoding="utf-8")
1957+
1958+
# LLM generates optimization with an inner class that has its own field.
1959+
# The inner class's field should NOT be injected into Outer.
1960+
optimized_markdown = f"""```java:{java_file.relative_to(tmp_path)}
1961+
public class Outer {{
1962+
private int count;
1963+
private static final int OFFSET = 10;
1964+
1965+
public int process(int x) {{
1966+
return x + count + OFFSET;
1967+
}}
1968+
1969+
private static class Inner {{
1970+
private final String badField;
1971+
1972+
Inner(String s) {{
1973+
this.badField = s;
1974+
}}
1975+
}}
1976+
}}
1977+
```"""
1978+
1979+
optimized_code = CodeStringsMarkdown.parse_markdown_code(optimized_markdown, expected_language="java")
1980+
1981+
function_to_optimize = FunctionToOptimize(
1982+
function_name="process",
1983+
file_path=java_file,
1984+
starting_line=4,
1985+
ending_line=6,
1986+
parents=[FunctionParent(name="Outer", type="ClassDef")],
1987+
qualified_name="Outer.process",
1988+
is_method=True,
1989+
)
1990+
1991+
result = java_support.replace_function_definitions(
1992+
function_names=["process"],
1993+
optimized_code=optimized_code,
1994+
module_abspath=java_file,
1995+
project_root_path=tmp_path,
1996+
function_to_optimize=function_to_optimize,
1997+
)
1998+
1999+
assert result is True
2000+
new_code = java_file.read_text(encoding="utf-8")
2001+
2002+
# Only OFFSET field should be added (belongs to Outer).
2003+
# badField belongs to Inner and should NOT appear.
2004+
assert "OFFSET" in new_code
2005+
assert "badField" not in new_code

0 commit comments

Comments
 (0)