Skip to content

Commit 79fbd2b

Browse files
misrasaurabh1claude
andcommitted
feat: support Java optimizations with static fields and helper methods
Add support for Java optimizations that include new class-level members: - Static fields (e.g., lookup tables like BYTE_TO_HEX) - Helper methods (e.g., createByteToHex()) - Precomputed arrays Changes: - Add _add_java_class_members() in code_replacer.py to detect and insert new class members from optimized code into the original source - Update _add_global_declarations_for_language() to handle Java - Add ParsedOptimization dataclass and supporting functions in replacement.py - Exclude target functions from being added as helpers (they're replaced) Tests: - Add TestOptimizationWithStaticFields (3 tests) - Add TestOptimizationWithHelperMethods (2 tests) - Add TestOptimizationWithFieldsAndHelpers (2 tests including real-world bytesToHexString optimization pattern) All 28 Java replacement tests and 32 instrumentation tests pass. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 3f53302 commit 79fbd2b

3 files changed

Lines changed: 788 additions & 8 deletions

File tree

codeflash/code_utils/code_replacer.py

Lines changed: 120 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ def replace_function_definitions_for_language(
515515
original_source=original_source_code,
516516
module_abspath=module_abspath,
517517
language=language,
518+
target_function_names=function_names,
518519
)
519520

520521
# If we have function_to_optimize with line info and this is the main file, use it for precise replacement
@@ -621,27 +622,142 @@ def _extract_function_from_code(
621622
return None
622623

623624

625+
def _add_java_class_members(
626+
optimized_code: str, original_source: str, target_function_names: list[str] | None = None
627+
) -> str:
628+
"""Add new Java class members (static fields and helper methods) from optimized code.
629+
630+
Parses both the optimized and original code to find:
631+
- New static fields in the optimized code that don't exist in the original
632+
- New helper methods in the optimized code that don't exist in the original
633+
634+
These are added to the original class at appropriate positions.
635+
Target functions (being replaced) are NOT added as new helpers.
636+
637+
Args:
638+
optimized_code: The optimized code that may contain new class members.
639+
original_source: The original source code.
640+
target_function_names: List of function names being optimized (to exclude from helpers).
641+
642+
Returns:
643+
Original source with new class members added.
644+
645+
"""
646+
target_names = set(target_function_names or [])
647+
try:
648+
from codeflash.languages.java.parser import get_java_analyzer
649+
650+
analyzer = get_java_analyzer()
651+
652+
# Find classes in both sources
653+
original_classes = analyzer.find_classes(original_source)
654+
optimized_classes = analyzer.find_classes(optimized_code)
655+
656+
if not original_classes or not optimized_classes:
657+
return original_source
658+
659+
# Match by class name (handle single class per file - most common case)
660+
# Use the first class as the target
661+
original_class = original_classes[0]
662+
optimized_class = None
663+
for cls in optimized_classes:
664+
if cls.name == original_class.name:
665+
optimized_class = cls
666+
break
667+
668+
if not optimized_class:
669+
# Try to use first class from optimized if names don't match
670+
optimized_class = optimized_classes[0]
671+
672+
class_name = original_class.name
673+
674+
# Find existing fields and methods in original
675+
existing_fields = analyzer.find_fields(original_source, class_name)
676+
existing_methods = analyzer.find_methods(original_source)
677+
existing_field_names = {f.name for f in existing_fields}
678+
existing_method_names = {m.name for m in existing_methods if m.class_name == class_name}
679+
680+
# Find fields and methods in optimized code
681+
optimized_fields = analyzer.find_fields(optimized_code, class_name)
682+
optimized_methods = analyzer.find_methods(optimized_code)
683+
684+
# Find new fields (fields in optimized that don't exist in original)
685+
new_fields = []
686+
for field in optimized_fields:
687+
if field.name not in existing_field_names:
688+
if field.source_text:
689+
new_fields.append(field.source_text)
690+
691+
# Find new helper methods (methods in optimized that don't exist in original)
692+
new_methods = []
693+
for method in optimized_methods:
694+
# Exclude target functions (they'll be replaced, not added as new helpers)
695+
if (
696+
method.class_name == class_name
697+
and method.name not in existing_method_names
698+
and method.name not in target_names
699+
):
700+
# Extract method source including Javadoc
701+
lines = optimized_code.splitlines(keepends=True)
702+
start = (method.javadoc_start_line or method.start_line) - 1
703+
end = method.end_line
704+
method_source = "".join(lines[start:end])
705+
new_methods.append(method_source)
706+
707+
if not new_fields and not new_methods:
708+
return original_source
709+
710+
logger.debug(
711+
f"Adding {len(new_fields)} new fields and {len(new_methods)} helper methods to class {class_name}"
712+
)
713+
714+
# Import the insertion function from replacement module
715+
from codeflash.languages.java.replacement import _insert_class_members
716+
717+
result = _insert_class_members(
718+
original_source, class_name, new_fields, new_methods, analyzer
719+
)
720+
721+
return result
722+
723+
except Exception as e:
724+
logger.debug(f"Error adding Java class members: {e}")
725+
return original_source
726+
727+
624728
def _add_global_declarations_for_language(
625-
optimized_code: str, original_source: str, module_abspath: Path, language: Language
729+
optimized_code: str,
730+
original_source: str,
731+
module_abspath: Path,
732+
language: Language,
733+
target_function_names: list[str] | None = None,
626734
) -> str:
627735
"""Add new global declarations from optimized code to original source.
628736
629-
Finds module-level declarations (const, let, var, class, type, interface, enum)
737+
For JavaScript/TypeScript: Finds module-level declarations (const, let, var, class, type, interface, enum)
630738
in the optimized code that don't exist in the original source and adds them.
631739
740+
For Java: Finds new static fields and helper methods in the optimized code that don't exist
741+
in the original source and adds them to the appropriate class.
742+
632743
Args:
633744
optimized_code: The optimized code that may contain new declarations.
634745
original_source: The original source code.
635746
module_abspath: Path to the module file (for parser selection).
636747
language: The language of the code.
748+
target_function_names: List of function names being optimized (to exclude from Java helpers).
637749
638750
Returns:
639-
Original source with new declarations added after imports.
751+
Original source with new declarations added.
640752
641753
"""
642754
from codeflash.languages.base import Language
643755

644-
# Only process JavaScript/TypeScript
756+
# Handle Java class-level members
757+
if language == Language.JAVA:
758+
return _add_java_class_members(optimized_code, original_source, target_function_names)
759+
760+
# Only process JavaScript/TypeScript for module-level declarations
645761
if language not in (Language.JAVASCRIPT, Language.TYPESCRIPT):
646762
return original_source
647763

0 commit comments

Comments
 (0)