mirror of
https://github.com/codeflash-ai/codeflash.git
synced 2026-05-04 18:25:17 +00:00
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:
parent
fdf74e255b
commit
207d01b56d
4 changed files with 64 additions and 21 deletions
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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()]
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
|
|
|||
Loading…
Reference in a new issue