@@ -1929,3 +1929,240 @@ 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 TestUnusedAdditionsRejection :
1935+ """Tests that optimizations adding unused fields/helpers with unchanged target method are rejected."""
1936+
1937+ def test_unchanged_method_with_unused_field_rejected (self , tmp_path : Path , java_support : JavaSupport ):
1938+ """An optimization that adds a field but doesn't change the method should be rejected."""
1939+ java_file = (tmp_path / "SystemUtils.java" ).resolve ()
1940+ original_code = """public class SystemUtils {
1941+ public static String getJavaIoTmpdir() {
1942+ return System.getProperty("java.io.tmpdir");
1943+ }
1944+ }
1945+ """
1946+ java_file .write_text (original_code , encoding = "utf-8" )
1947+
1948+ # AI adds NULL_SUPPLIER but doesn't change getJavaIoTmpdir
1949+ optimized_markdown = f"""```java:{ java_file .relative_to (tmp_path )}
1950+ public class SystemUtils {{
1951+ private static final String CACHED_TMPDIR = System.getProperty("java.io.tmpdir");
1952+
1953+ public static String getJavaIoTmpdir() {{
1954+ return System.getProperty("java.io.tmpdir");
1955+ }}
1956+ }}
1957+ ```"""
1958+
1959+ optimized_code = CodeStringsMarkdown .parse_markdown_code (optimized_markdown , expected_language = "java" )
1960+
1961+ from codeflash .discovery .functions_to_optimize import FunctionParent , FunctionToOptimize
1962+
1963+ function_to_optimize = FunctionToOptimize (
1964+ function_name = "getJavaIoTmpdir" ,
1965+ file_path = java_file ,
1966+ starting_line = 2 ,
1967+ ending_line = 4 ,
1968+ parents = [FunctionParent (name = "SystemUtils" , type = "ClassDef" )],
1969+ qualified_name = "SystemUtils.getJavaIoTmpdir" ,
1970+ is_method = True ,
1971+ )
1972+
1973+ result = replace_function_definitions_for_language (
1974+ function_names = ["getJavaIoTmpdir" ],
1975+ optimized_code = optimized_code ,
1976+ module_abspath = java_file ,
1977+ project_root_path = tmp_path ,
1978+ lang_support = java_support ,
1979+ function_to_optimize = function_to_optimize ,
1980+ )
1981+
1982+ # Should reject: method unchanged, field unreferenced
1983+ assert result is False
1984+ assert java_file .read_text (encoding = "utf-8" ) == original_code
1985+
1986+ def test_unchanged_method_with_unused_helper_rejected (self , tmp_path : Path , java_support : JavaSupport ):
1987+ """An optimization that adds a helper method but doesn't change the target should be rejected."""
1988+ java_file = (tmp_path / "Calculator.java" ).resolve ()
1989+ original_code = """public class Calculator {
1990+ public int add(int a, int b) {
1991+ return a + b;
1992+ }
1993+ }
1994+ """
1995+ java_file .write_text (original_code , encoding = "utf-8" )
1996+
1997+ # AI adds a helper method but doesn't change add()
1998+ optimized_markdown = f"""```java:{ java_file .relative_to (tmp_path )}
1999+ public class Calculator {{
2000+ private static int fastAdd(int a, int b) {{
2001+ return Math.addExact(a, b);
2002+ }}
2003+
2004+ public int add(int a, int b) {{
2005+ return a + b;
2006+ }}
2007+ }}
2008+ ```"""
2009+
2010+ optimized_code = CodeStringsMarkdown .parse_markdown_code (optimized_markdown , expected_language = "java" )
2011+
2012+ from codeflash .discovery .functions_to_optimize import FunctionParent , FunctionToOptimize
2013+
2014+ function_to_optimize = FunctionToOptimize (
2015+ function_name = "add" ,
2016+ file_path = java_file ,
2017+ starting_line = 2 ,
2018+ ending_line = 4 ,
2019+ parents = [FunctionParent (name = "Calculator" , type = "ClassDef" )],
2020+ qualified_name = "Calculator.add" ,
2021+ is_method = True ,
2022+ )
2023+
2024+ result = replace_function_definitions_for_language (
2025+ function_names = ["add" ],
2026+ optimized_code = optimized_code ,
2027+ module_abspath = java_file ,
2028+ project_root_path = tmp_path ,
2029+ lang_support = java_support ,
2030+ function_to_optimize = function_to_optimize ,
2031+ )
2032+
2033+ # Should reject: method unchanged, helper unreferenced
2034+ assert result is False
2035+ assert java_file .read_text (encoding = "utf-8" ) == original_code
2036+
2037+ def test_changed_method_with_used_field_accepted (self , tmp_path : Path , java_support : JavaSupport ):
2038+ """An optimization that adds a field AND uses it in the changed method should be accepted."""
2039+ java_file = (tmp_path / "SystemUtils.java" ).resolve ()
2040+ original_code = """public class SystemUtils {
2041+ public static String getJavaIoTmpdir() {
2042+ return System.getProperty("java.io.tmpdir");
2043+ }
2044+ }
2045+ """
2046+ java_file .write_text (original_code , encoding = "utf-8" )
2047+
2048+ # AI adds CACHED_TMPDIR and actually uses it in the method
2049+ optimized_markdown = f"""```java:{ java_file .relative_to (tmp_path )}
2050+ public class SystemUtils {{
2051+ private static final String CACHED_TMPDIR = System.getProperty("java.io.tmpdir");
2052+
2053+ public static String getJavaIoTmpdir() {{
2054+ return CACHED_TMPDIR;
2055+ }}
2056+ }}
2057+ ```"""
2058+
2059+ optimized_code = CodeStringsMarkdown .parse_markdown_code (optimized_markdown , expected_language = "java" )
2060+
2061+ from codeflash .discovery .functions_to_optimize import FunctionParent , FunctionToOptimize
2062+
2063+ function_to_optimize = FunctionToOptimize (
2064+ function_name = "getJavaIoTmpdir" ,
2065+ file_path = java_file ,
2066+ starting_line = 2 ,
2067+ ending_line = 4 ,
2068+ parents = [FunctionParent (name = "SystemUtils" , type = "ClassDef" )],
2069+ qualified_name = "SystemUtils.getJavaIoTmpdir" ,
2070+ is_method = True ,
2071+ )
2072+
2073+ result = replace_function_definitions_for_language (
2074+ function_names = ["getJavaIoTmpdir" ],
2075+ optimized_code = optimized_code ,
2076+ module_abspath = java_file ,
2077+ project_root_path = tmp_path ,
2078+ lang_support = java_support ,
2079+ function_to_optimize = function_to_optimize ,
2080+ )
2081+
2082+ # Should accept: method changed to use CACHED_TMPDIR
2083+ assert result is True
2084+ new_code = java_file .read_text (encoding = "utf-8" )
2085+ assert "CACHED_TMPDIR" in new_code
2086+ assert "private static final String CACHED_TMPDIR" in new_code
2087+
2088+ def test_changed_method_without_additions_accepted (self , tmp_path : Path , java_support : JavaSupport ):
2089+ """A normal optimization that just changes the method body should be accepted."""
2090+ java_file = (tmp_path / "Calculator.java" ).resolve ()
2091+ original_code = """public class Calculator {
2092+ public int add(int a, int b) {
2093+ return a + b;
2094+ }
2095+ }
2096+ """
2097+ java_file .write_text (original_code , encoding = "utf-8" )
2098+
2099+ optimized_markdown = f"""```java:{ java_file .relative_to (tmp_path )}
2100+ public class Calculator {{
2101+ public int add(int a, int b) {{
2102+ return Math.addExact(a, b);
2103+ }}
2104+ }}
2105+ ```"""
2106+
2107+ optimized_code = CodeStringsMarkdown .parse_markdown_code (optimized_markdown , expected_language = "java" )
2108+
2109+ result = replace_function_definitions_for_language (
2110+ function_names = ["add" ],
2111+ optimized_code = optimized_code ,
2112+ module_abspath = java_file ,
2113+ project_root_path = tmp_path ,
2114+ lang_support = java_support ,
2115+ )
2116+
2117+ # Should accept: method was changed
2118+ assert result is True
2119+
2120+ def test_unchanged_method_with_used_helper_accepted (self , tmp_path : Path , java_support : JavaSupport ):
2121+ """Method unchanged but references the new helper — should be accepted (helper IS used)."""
2122+ java_file = (tmp_path / "Calculator.java" ).resolve ()
2123+ original_code = """public class Calculator {
2124+ public int add(int a, int b) {
2125+ return a + b;
2126+ }
2127+ }
2128+ """
2129+ java_file .write_text (original_code , encoding = "utf-8" )
2130+
2131+ # AI adds helper AND rewrites method to use it
2132+ optimized_markdown = f"""```java:{ java_file .relative_to (tmp_path )}
2133+ public class Calculator {{
2134+ private static int fastAdd(int a, int b) {{
2135+ return Math.addExact(a, b);
2136+ }}
2137+
2138+ public int add(int a, int b) {{
2139+ return fastAdd(a, b);
2140+ }}
2141+ }}
2142+ ```"""
2143+
2144+ optimized_code = CodeStringsMarkdown .parse_markdown_code (optimized_markdown , expected_language = "java" )
2145+
2146+ from codeflash .discovery .functions_to_optimize import FunctionParent , FunctionToOptimize
2147+
2148+ function_to_optimize = FunctionToOptimize (
2149+ function_name = "add" ,
2150+ file_path = java_file ,
2151+ starting_line = 2 ,
2152+ ending_line = 4 ,
2153+ parents = [FunctionParent (name = "Calculator" , type = "ClassDef" )],
2154+ qualified_name = "Calculator.add" ,
2155+ is_method = True ,
2156+ )
2157+
2158+ result = replace_function_definitions_for_language (
2159+ function_names = ["add" ],
2160+ optimized_code = optimized_code ,
2161+ module_abspath = java_file ,
2162+ project_root_path = tmp_path ,
2163+ lang_support = java_support ,
2164+ function_to_optimize = function_to_optimize ,
2165+ )
2166+
2167+ # Should accept: method changed to call fastAdd
2168+ assert result is True
0 commit comments