Disable build cache for Gradle and Maven builds and fix var-typed instrumentation capture

- Add --no-build-cache flag to all Gradle build commands to ensure fresh compilation
- Add -Dmaven.build.cache.enabled=false to Maven validation skip flags
- Fix Java instrumentation to use var-typed capture instead of Object for method chaining support
- Update instrumentation tests to reflect new var-based capture pattern

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
HeshamHM28 2026-04-02 14:55:43 +00:00 committed by Ubuntu
parent fdf74e255b
commit 207d01b56d
4 changed files with 64 additions and 21 deletions

View file

@ -469,7 +469,7 @@ class GradleStrategy(BuildToolStrategy):
logger.error("Gradle not found — cannot pre-install multi-module dependencies")
return False
cmd = [gradle, f":{test_module}:classes", "-x", "test", "--build-cache", "--no-daemon"]
cmd = [gradle, f":{test_module}:classes", "-x", "test", "--no-build-cache", "--no-daemon"]
cmd.extend(["--init-script", _get_skip_validation_init_script()])
logger.info("Pre-installing multi-module dependencies: %s (module: %s)", build_root, test_module)
@ -504,9 +504,9 @@ class GradleStrategy(BuildToolStrategy):
return subprocess.CompletedProcess(args=["gradle"], returncode=-1, stdout="", stderr="Gradle not found")
if test_module:
cmd = [gradle, f":{test_module}:testClasses", "--no-daemon"]
cmd = [gradle, f":{test_module}:testClasses", "--no-build-cache", "--no-daemon"]
else:
cmd = [gradle, "testClasses", "--no-daemon"]
cmd = [gradle, "testClasses", "--no-build-cache", "--no-daemon"]
cmd.extend(["--init-script", _get_skip_validation_init_script()])
logger.debug("Compiling tests: %s in %s", " ".join(cmd), build_root)
@ -528,9 +528,9 @@ class GradleStrategy(BuildToolStrategy):
return subprocess.CompletedProcess(args=["gradle"], returncode=-1, stdout="", stderr="Gradle not found")
if test_module:
cmd = [gradle, f":{test_module}:classes", "--no-daemon"]
cmd = [gradle, f":{test_module}:classes", "--no-build-cache", "--no-daemon"]
else:
cmd = [gradle, "classes", "--no-daemon"]
cmd = [gradle, "classes", "--no-build-cache", "--no-daemon"]
cmd.extend(["--init-script", _get_skip_validation_init_script()])
logger.debug("Compiling source only: %s in %s", " ".join(cmd), build_root)
@ -574,7 +574,7 @@ class GradleStrategy(BuildToolStrategy):
else:
task = "codeflashPrintClasspath"
cmd = [gradle, "--init-script", init_script_path, task, "-q", "--no-daemon"]
cmd = [gradle, "--init-script", init_script_path, task, "-q", "--no-build-cache", "--no-daemon"]
logger.debug("Getting classpath: %s", " ".join(cmd))
@ -725,7 +725,7 @@ class GradleStrategy(BuildToolStrategy):
with os.fdopen(init_fd, "w", encoding="utf-8") as f:
f.write(init_script_content)
cmd = [gradle, task, "--no-daemon", "--rerun", "--init-script", init_path]
cmd = [gradle, task, "--no-build-cache", "--no-daemon", "--rerun", "--init-script", init_path]
cmd.extend(["--init-script", _get_skip_validation_init_script()])
# --continue ensures Gradle keeps going even if some tests fail.
@ -952,7 +952,7 @@ class GradleStrategy(BuildToolStrategy):
raise ValueError(msg)
gradle = self.find_executable(project_root) or "gradle"
cmd = [gradle, "test", "--no-daemon"]
cmd = [gradle, "test", "--no-build-cache", "--no-daemon"]
if test_classes:
for cls in test_classes:
cmd.extend(["--tests", cls])

View file

@ -391,17 +391,50 @@ def wrap_target_calls_with_treesitter(
line_char_start = call["_line_char_start"]
if precise_call_timing:
prefix_lines = [
f"{line_indent_str}Object {var_name} = null;",
# For embedded calls, the original line uses the captured variable inline
# (e.g., builder().model("x") becomes _cf_result.model("x")).
# Using `Object` loses the type and breaks method chaining (builder pattern).
# Fix: use `var` to capture with type inference inside the try block, and
# move the original line (with call replaced) INTO the try block so the
# `var`-typed variable is in scope. A separate Object variable handles
# serialization in the finally block.
#
# Generated structure:
# Object _cf_obj = null;
# try {
# var _cf_result = targetCall();
# _cf_obj = _cf_result;
# serialize(_cf_obj);
# <original line with call replaced by _cf_result>
# } finally { ... }
obj_var = f"_cf_obj{iter_id}_{call_counter}"
typed_capture = f"var {var_name} = {call['full_call']};"
obj_assign = f"{obj_var} = {var_name};"
typed_serialize = f"_cf_serializedResult{iter_id}_{call_counter} = com.codeflash.Serializer.serialize((Object) {var_name});"
# Step 1: Replace the call in the original line with the typed var
modified_line_text = body_text[line_char_start:]
# Adjust offsets relative to line start
rel_call_start = call_start - line_char_start
rel_call_end = call_end - line_char_start
modified_line_text_before_eol = modified_line_text.split("\n", 1)
orig_line_text = modified_line_text_before_eol[0]
# Replace the call within the original line
orig_line_with_var = orig_line_text[:rel_call_start] + var_name + orig_line_text[rel_call_end:]
pre_lines = [
f"{line_indent_str}Object {obj_var} = null;",
f"{line_indent_str}long _cf_end{iter_id}_{call_counter} = -1;",
f"{line_indent_str}long _cf_start{iter_id}_{call_counter} = 0;",
f"{line_indent_str}byte[] _cf_serializedResult{iter_id}_{call_counter} = null;",
f'{line_indent_str}System.out.println("!$######" + _cf_mod{iter_id} + ":" + _cf_cls{iter_id} + "." + _cf_test{iter_id} + ":" + _cf_fn{iter_id} + ":" + _cf_loop{iter_id} + ":{inv_id}" + "######$!");',
f"{line_indent_str}try {{",
f"{line_indent_str} {start_stmt}",
f"{line_indent_str} {capture_stmt_assign}",
f"{line_indent_str} {typed_capture}",
f"{line_indent_str} {end_stmt}",
f"{line_indent_str} {serialize_stmt}",
f"{line_indent_str} {obj_assign}",
f"{line_indent_str} {typed_serialize}",
f"{line_indent_str} {orig_line_with_var.strip()}",
]
finally_lines = _generate_sqlite_write_code(
iter_id,
@ -412,15 +445,23 @@ def wrap_target_calls_with_treesitter(
test_method_name,
invocation_id=inv_id,
)
prefix_lines.extend(finally_lines)
pre_lines.extend(finally_lines)
# Replace the entire original line with the instrumented block
# Find the end of the original line
next_newline = body_text.find("\n", line_char_start)
if next_newline == -1:
next_newline = len(body_text)
replacement_text = "\n".join(pre_lines)
body_text = body_text[:line_char_start] + replacement_text + body_text[next_newline:]
else:
prefix_lines = [f"{line_indent_str}{capture_stmt_with_decl}", f"{line_indent_str}{serialize_stmt}"]
# Step 1: Replace the call with the variable (at higher offset, safe to do first)
body_text = body_text[:call_start] + var_with_cast + body_text[call_end:]
# Step 2: Insert prefix lines before the line containing the call (at lower offset)
prefix_text = "\n".join(prefix_lines) + "\n"
body_text = body_text[:line_char_start] + prefix_text + body_text[line_char_start:]
# Step 1: Replace the call with the variable (at higher offset, safe to do first)
body_text = body_text[:call_start] + var_with_cast + body_text[call_end:]
# Step 2: Insert prefix lines before the line containing the call (at lower offset)
prefix_text = "\n".join(prefix_lines) + "\n"
body_text = body_text[:line_char_start] + prefix_text + body_text[line_char_start:]
# Split back into lines, filtering out any lines that became empty from statement replacement
wrapped = [line for line in body_text.split("\n") if line.strip()]

View file

@ -45,6 +45,7 @@ _MAVEN_VALIDATION_SKIP_FLAGS = [
"-Derrorprone.skip=true",
"-Dmaven.compiler.failOnWarning=false",
"-Dmaven.compiler.showWarnings=false",
"-Dmaven.build.cache.enabled=false",
]
# Cache for classpath strings — keyed on (maven_root, test_module).

View file

@ -145,16 +145,18 @@ public class CalculatorTest__perfinstrumented {
if (_cf_testIteration1 == null) _cf_testIteration1 = "0";
String _cf_test1 = "testAdd";
Calculator calc = new Calculator();
Object _cf_result1_1 = null;
Object _cf_obj1_1 = null;
long _cf_end1_1 = -1;
long _cf_start1_1 = 0;
byte[] _cf_serializedResult1_1 = null;
System.out.println("!$######" + _cf_mod1 + ":" + _cf_cls1 + "." + _cf_test1 + ":" + _cf_fn1 + ":" + _cf_loop1 + ":L11_1" + "######$!");
try {
_cf_start1_1 = System.nanoTime();
_cf_result1_1 = calc.add(2, 2);
var _cf_result1_1 = calc.add(2, 2);
_cf_end1_1 = System.nanoTime();
_cf_obj1_1 = _cf_result1_1;
_cf_serializedResult1_1 = com.codeflash.Serializer.serialize((Object) _cf_result1_1);
assertEquals(4, _cf_result1_1);
} finally {
long _cf_end1_1_finally = System.nanoTime();
long _cf_dur1_1 = (_cf_end1_1 != -1 ? _cf_end1_1 : _cf_end1_1_finally) - _cf_start1_1;
@ -189,7 +191,6 @@ public class CalculatorTest__perfinstrumented {
}
}
}
assertEquals(4, _cf_result1_1);
}
}
"""