feat(java): skip inner-class methods in discovery; revert replacement-level workarounds - #1726
Merged
Merged
Conversation
…(Java) When the optimisation target lives in a static inner class (e.g. ObjectUnpacker inside Unpacker<T>), the LLM-generated class often wraps the inner class inside the full outer class. Previously, methods belonging to the outer class were extracted as "helpers" and injected into the inner class, causing compilation errors: - "non-static type variable T cannot be referenced from a static context" - "non-static variable offset cannot be referenced from a static context" Two related fixes: 1. When _parse_optimization_source extracts helpers, it now skips any method whose class_name differs from the target method's class_name. 2. The function now accepts an optional target_class_name parameter. When there are multiple methods with the same name in the generated code (e.g. an abstract outer-class method and the concrete inner-class override), the method in the target class is preferred over outer-class methods. Fixes the Unpacker.ObjectUnpacker.getString regression from codeflash_all_3.log. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When the LLM optimises a method by introducing a new final field (e.g. caching Arrays.hashCode in Expression.hashCode, or caching map.values() in LuaMap.valuesIterator), it also modifies the class constructors to initialise the field. Previously codeflash: 1. Added the new field to the class ✓ 2. Replaced the target method ✓ 3. Did NOT update the constructors ✗ This caused "variable X might not have been initialized" compilation errors. Changes: - `JavaAnalyzer.find_constructors` (+ `_walk_tree_for_constructors`, `_extract_constructor_info`): new parser methods to locate `constructor_declaration` nodes via tree-sitter. - `JavaMethodNode.formal_parameters_text`: captures the raw parameter list text so constructors can be matched by signature. - `ParsedOptimization.modified_constructors`: new field to carry constructor source texts that need to be replaced. - `_parse_optimization_source`: extract constructors from the same class as the target method and store in `modified_constructors`. - `_replace_constructors`: new helper that replaces constructors in the original source by matching on formal parameter signature. - `replace_function`: call `_replace_constructors` after the main method replacement when `modified_constructors` is non-empty. Fixes regressions observed in codeflash_all_3.log: LuaMap.valuesIterator, Expression.hashCode, Bin.hashCode, NettyTlsContext.createHandler, Pool.capacity. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cement fix(java): replace modified constructors when LLM adds new final fields
…level inner-class workarounds - parser.py: add `is_class_nested` flag to `JavaMethodNode`; track `class_depth` in `_walk_tree_for_methods` (incremented each time a type declaration is entered) and set `is_class_nested = True` when depth ≥ 2 (method lives inside a nested/inner class) - discovery.py: add early-exit in `_should_include_method` when `method.is_class_nested` is True — inner-class methods cannot be reliably instrumented or tested in isolation, so we skip them up-front rather than wasting LLM tokens on candidates that will always be rejected later - replacement.py: revert Bug-4 replacement-level workarounds that are now obsolete: * remove `target_class_name` parameter from `_parse_optimization_source` * restore simple first-match `break` in target-method selection * remove class_name filter that blocked helpers from "other" classes - tests: update `TestNestedClasses`, `TestExtractCodeContextWithInnerClasses` to reflect the new no-inner-class-discovery contract; remove `TestInnerClassHelperFilter` (superseded by discovery filter); add `TestInnerClassMethodFilter` in test_discovery.py with four scenarios covering static nested, non-static inner, outer-only, and deeply-nested classes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
KRRT7
added a commit
that referenced
this pull request
Mar 4, 2026
Inner-class methods are intentionally skipped by Java discovery (PR #1726) since instrumentation is name-only and not class-aware. Update test to expect False from replacement.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
is_class_nestedflag toJavaMethodNode; trackclass_depthin_walk_tree_for_methods(incremented on each type declaration entry). Methods at depth ≥ 2 haveis_class_nested = True.is_class_nested = Truein_should_include_method. Inner-class methods cannot be reliably instrumented (instrumentation is name-only, not class-aware), and non-static inner classes require an outer instance unavailable in tests.target_class_nameparameter, restoring simple first-match selection, and removing the class-name filter for helpers.TestInnerClassMethodFilterintest_discovery.pywith four scenarios (static nested, non-static inner, outer-only, deeply nested).Test plan
uv run python -m pytest tests/test_languages/test_java/test_discovery.py— newTestInnerClassMethodFilterclass passesuv run python -m pytest tests/test_languages/test_java/test_replacement.py— all pass (removed obsoleteTestInnerClassHelperFilter)uv run python -m pytest tests/test_languages/test_java/test_context.py— updated inner-class context tests pass🤖 Generated with Claude Code