From 93cadc0ae005758ae8ef6e297f965f3a2b76283e Mon Sep 17 00:00:00 2001 From: "Tapabrata \"Topo\" Pal" Date: Sat, 10 Oct 2026 22:33:32 -0400 Subject: [PATCH 1/7] harness: deep16 seeded task set, builder and scorer support 16 multi-file seeded tasks (deep__*) built by build_deep.py from per-language recipes; wide_eval shape-mode site scoring, js_eval typecheck_cmd, and the bench monitor/pair reporter used for the 2026-10-10 native vs prism v0.87.2 baseline (results/bench-deep-2026-10-10). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01KXa6Cv1ZUXcdMqXcJfQFhX --- harness/build/build_deep.py | 277 + harness/build/build_wide.py | 69 +- harness/build/deep_edit.py | 183 + harness/build/deep_recipes_go.py | 458 ++ harness/build/deep_recipes_java.py | 465 ++ harness/build/deep_recipes_py.py | 405 ++ harness/build/deep_recipes_ts.py | 537 ++ harness/scoring/bench_monitor.py | 18 +- harness/scoring/bench_pairs.py | 7 +- harness/scoring/js_eval.py | 28 +- harness/scoring/wide_eval.py | 107 +- ...cli__ValueCreator_Create_return_error.json | 1230 ++++ ...areConfigurator_ToMiddleware_add_echo.json | 1380 +++++ ...deep__echo__NewHTTPError_add_internal.json | 1375 +++++ ...flask__add_url_rule_endpoint_required.json | 606 ++ ...deep__gin__Binding_Bind_add_validator.json | 1202 ++++ ...n__TypeAdapterFactory_create_Optional.json | 276 + .../e2e/deep__h3__H3Event_module_move.json | 1296 ++++ ...p__hono__HTTPException_options_object.json | 4238 +++++++++++++ .../e2e/deep__hono__getConnInfo_async.json | 4268 +++++++++++++ ...atabind__NameTransformer_move_package.json | 4028 ++++++++++++ ..._acceptJsonFormatVisitor_add_provider.json | 4061 +++++++++++++ ...n-databind__supportsUpdate_OptBoolean.json | 4012 ++++++++++++ .../deep__rich__Measurement_move_module.json | 1015 ++++ .../deep__rich__loop_helpers_value_first.json | 996 +++ ...erkzeug__create_environ_inline_remove.json | 1006 +++ .../e2e/deep__zod__codec_options_object.json | 5394 +++++++++++++++++ 27 files changed, 38919 insertions(+), 18 deletions(-) create mode 100644 harness/build/build_deep.py create mode 100644 harness/build/deep_edit.py create mode 100644 harness/build/deep_recipes_go.py create mode 100644 harness/build/deep_recipes_java.py create mode 100644 harness/build/deep_recipes_py.py create mode 100644 harness/build/deep_recipes_ts.py create mode 100644 harness/tasks/e2e/deep__cli__ValueCreator_Create_return_error.json create mode 100644 harness/tasks/e2e/deep__echo__MiddlewareConfigurator_ToMiddleware_add_echo.json create mode 100644 harness/tasks/e2e/deep__echo__NewHTTPError_add_internal.json create mode 100644 harness/tasks/e2e/deep__flask__add_url_rule_endpoint_required.json create mode 100644 harness/tasks/e2e/deep__gin__Binding_Bind_add_validator.json create mode 100644 harness/tasks/e2e/deep__gson__TypeAdapterFactory_create_Optional.json create mode 100644 harness/tasks/e2e/deep__h3__H3Event_module_move.json create mode 100644 harness/tasks/e2e/deep__hono__HTTPException_options_object.json create mode 100644 harness/tasks/e2e/deep__hono__getConnInfo_async.json create mode 100644 harness/tasks/e2e/deep__jackson-databind__NameTransformer_move_package.json create mode 100644 harness/tasks/e2e/deep__jackson-databind__acceptJsonFormatVisitor_add_provider.json create mode 100644 harness/tasks/e2e/deep__jackson-databind__supportsUpdate_OptBoolean.json create mode 100644 harness/tasks/e2e/deep__rich__Measurement_move_module.json create mode 100644 harness/tasks/e2e/deep__rich__loop_helpers_value_first.json create mode 100644 harness/tasks/e2e/deep__werkzeug__create_environ_inline_remove.json create mode 100644 harness/tasks/e2e/deep__zod__codec_options_object.json diff --git a/harness/build/build_deep.py b/harness/build/build_deep.py new file mode 100644 index 00000000..fffb65d5 --- /dev/null +++ b/harness/build/build_deep.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python3 +"""Seeded DEEP tasks: authored signature/type changes too wide and too +context-dependent for one text substitution (add a required parameter, +change a return type, move a type to another package). + +Each recipe below makes the gold change mechanically in a fresh checkout: +declarations by pattern, call sites from the compiler's own error list +(Java/Go/TS) or by a resolved-name scan (Python), repeated until the build +is clean. The result is written as a gold patch plus a build_wide.py spec +(site_mode="shapes"); build_wide then measures base/gold shape counts, picks +pass_to_pass, and proves gold resolves, the empty patch fails and a partial +patch (gold minus a few sites, also made here) fails. + +usage: + build_deep.py gold # make gold + partial patches and the spec + build_deep.py build # gold, then build_wide (writes tasks/e2e/.json) + build_deep.py list +Work dirs live under $DEEP_WORK (default ~/.cache/deep-tasks). +""" +from __future__ import annotations + +import json +import os +import re +import shutil +import subprocess +import sys +from pathlib import Path + +H = Path(__file__).resolve().parent.parent +sys.path.insert(0, str(H / "build")) +sys.path.insert(0, str(H / "scoring")) +import deep_edit as de # noqa: E402 + +WORK = Path(os.environ.get("DEEP_WORK", Path.home() / ".cache" / "deep-tasks")) +CORPUS = Path.home() / "gvg-corpus" +M2 = Path.home() / ".m2-eval" + +RECIPES: dict[str, dict] = {} + + +def recipe(**meta): + def deco(fn): + RECIPES[meta["instance_id"]] = dict(meta, make=fn) + return fn + return deco + + +# ---------------------------------------------------------------- checkout + +def checkout(repo: Path, base: str, dest: Path) -> Path: + if dest.exists(): + shutil.rmtree(dest) + dest.parent.mkdir(parents=True, exist_ok=True) + de.git("clone", "--local", "--no-checkout", "--quiet", str(repo), str(dest)) + de.git("-C", str(dest), "checkout", "--detach", "-f", "-q", base) + return dest + + +def diff_of(wt: Path, exclude=("pom.xml",)) -> str: + de.git("-C", str(wt), "add", "-A") + ex = [f":(exclude){e}" for e in exclude] + return de.git("-C", str(wt), "diff", "--cached", "--", ".", *ex) + + +def read(wt: Path, f: str) -> str: + return (wt / f).read_text() + + +def write(wt: Path, f: str, text: str) -> None: + (wt / f).write_text(text) + + +# ---------------------------------------------------------------- java + +JAVA_ERR = re.compile(r"^\[ERROR\] /w/(\S+\.java):\[(\d+),(\d+)\] (.*)$", re.M) + + +def java_compile(wt: Path, image: str = "maven:3.9-eclipse-temurin-17") -> tuple[bool, list, str]: + """mvn test-compile in docker; (ok, [(file, line, col, msg)], tail).""" + import java_eval + java_eval._pin_snapshot_parent(wt) + cmd = "set -o pipefail; mvn -q -nsu test-compile 2>&1 | tail -400" + r = subprocess.run(["docker", "run", "--rm", "-v", f"{wt}:/w", "-v", f"{M2}:/root/.m2", + "-w", "/w", image, "bash", "-lc", cmd], + capture_output=True, text=True, timeout=3600) + out = r.stdout + r.stderr + errs = [(m.group(1), int(m.group(2)), int(m.group(3)), m.group(4)) for m in JAVA_ERR.finditer(out)] + # de-dup (maven prints the list twice) + seen, uniq = set(), [] + for e in errs: + if e not in seen: + seen.add(e) + uniq.append(e) + return r.returncode == 0, uniq, out[-3000:] + + +def line_offset(text: str, line: int, col: int = 1) -> int: + off = 0 + for _ in range(line - 1): + off = text.index("\n", off) + 1 + return off + col - 1 + + +def calls_near(wt: Path, f: str, name: str, line: int) -> list: + """Calls/decls of name whose name starts on the given line or (javac + points at the receiver's dot) the line after.""" + raw = read(wt, f) + m = de.mask(raw, f) + out = [] + for c in de.find_calls(raw, m, name): + ln = raw.count("\n", 0, c.name_start) + 1 + if ln in (line, line + 1): + out.append(c) + return out + + +def ensure_java_import(text: str, fqn: str) -> str: + simple = fqn.rsplit(".", 1)[1] + pkg = re.search(r"^package\s+([\w.]+);", text, re.M) + if pkg and pkg.group(1) == fqn.rsplit(".", 1)[0]: + return text + if re.search(rf"^import\s+{re.escape(fqn)};", text, re.M): + return text + if re.search(rf"^import\s+{re.escape(fqn.rsplit('.', 1)[0])}\.\*;", text, re.M): + return text + if re.search(rf"^import\s+[\w.]+\.{simple};", text, re.M): + raise RuntimeError(f"conflicting import for {simple}") + imps = list(re.finditer(r"^import\s+(static\s+)?[\w.*]+;\s*$", text, re.M)) + non_static = [m for m in imps if not m.group(1)] + anchor = (non_static or imps) + if anchor: + pos = anchor[-1].end() + return text[:pos] + f"\nimport {fqn};" + text[pos:] + pkg_m = re.search(r"^package\s+[\w.]+;\s*$", text, re.M) + pos = pkg_m.end() + return text[:pos] + f"\n\nimport {fqn};" + text[pos:] + + +def enclosing_java_params(raw: str, masked: str, pos: int) -> str: + """The parameter list text of the method enclosing pos (best effort: + the nearest preceding `name(...) [throws ...] {` whose body contains pos).""" + best = "" + for m in re.finditer(r"\b([\w$]+)\s*\(([^()]*(?:\([^()]*\)[^()]*)*)\)\s*(?:throws[\w\s.,]+)?\{", masked[:pos]): + if m.group(1) in ("if", "for", "while", "switch", "catch", "synchronized", "try", "return", "new"): + continue + prev = de.prev_token(masked, m.start(1)) + if not (prev and (prev[-1].isalnum() or prev[-1] in "_$>]")) or prev in ("new", "return", "else", "throw"): + continue + # body brace balance from the "{" to pos must stay > 0 + depth = 0 + ok = True + for ch in masked[m.end() - 1:pos]: + depth += ch == "{" + depth -= ch == "}" + if depth <= 0: + ok = False + break + if ok: + best = raw[m.start(2):m.end(2)] + return best + + +# ---------------------------------------------------------------- driver + +def task_dir(tid: str) -> Path: + return WORK / tid + + +def make_gold(tid: str) -> dict: + r = RECIPES[tid] + d = task_dir(tid) + d.mkdir(parents=True, exist_ok=True) + wt = checkout(r["repo_dir"], r["base_commit"], d / "wt") + info = r["make"](wt) or {} + gold = diff_of(wt) + (d / "gold.patch").write_text(gold) + partial = make_partial(wt, r, gold, info) + (d / "partial.patch").write_text(partial) + spec = {k: r[k] for k in ("instance_id", "repo", "lang", "base_commit", "instruction", "shapes")} + spec.update(source="seeded", site_mode="shapes", gold_patch=str(d / "gold.patch"), + partial_patch=str(d / "partial.patch"), gold_tool=r["gold_tool"], + change=r["change"], notes=r.get("notes", "") + (" " + info.get("notes", "") if info.get("notes") else "")) + for k in ("test_classes", "test_functions", "test_modules", "typecheck_cmd", "pytest_args"): + if k in r: + spec[k] = r[k] + (d / "spec.json").write_text(json.dumps(spec, indent=1)) + return spec + + +def make_partial(wt: Path, r: dict, gold: str, info: dict) -> str: + """Gold minus the hunks the recipe names (info["partial_drop"] = list of + (file, substring-in-hunk)), or by default the last hunk of the two + gold files with the most hunks -- a call/override update the agent + 'forgot'. Built by reverting those hunks in the gold tree.""" + files = re.split(r"(?m)^(?=diff --git )", gold) + files = [f for f in files if f.strip()] + drops = info.get("partial_drop") + out = [] + dropped = [] + if drops is None: + # files with >= 2 hunks, not the declaration file(s) + cand = [] + for fd in files: + name = re.search(r"^\+\+\+ b/(\S+)", fd, re.M) + if not name: + continue + n = len(re.findall(r"(?m)^@@", fd)) + if n >= 2 and name.group(1) not in r.get("decl_files", []): + cand.append((n, name.group(1))) + cand.sort(reverse=True) + drops = [(f, None) for _, f in cand[:2]] + if not drops: + drops = [(re.search(r"^\+\+\+ b/(\S+)", files[-1], re.M).group(1), None)] + dropmap = {} + for f, sub in drops: + dropmap.setdefault(f, []).append(sub) + for fd in files: + name = re.search(r"^\+\+\+ b/(\S+)", fd, re.M) + fname = name.group(1) if name else None + if fname not in dropmap: + out.append(fd) + continue + head, *hunks = re.split(r"(?m)^(?=@@)", fd) + keep = [] + subs = dropmap[fname] + for h in hunks: + hit = None + for s in subs: + if (s is None and h is hunks[-1]) or (s is not None and s in h): + hit = s + break + if hit is not None or (None in subs and h is hunks[-1]): + dropped.append(f"{fname}: {h.splitlines()[0]}") + continue + keep.append(h) + if keep: + out.append(head + "".join(keep)) + info.setdefault("dropped", dropped) + (task_dir(r["instance_id"]) / "partial.dropped.txt").write_text("\n".join(dropped)) + return "".join(out) + + +def build(tid: str) -> None: + spec = make_gold(tid) if not (task_dir(tid) / "spec.json").exists() or "--regold" in sys.argv \ + else json.loads((task_dir(tid) / "spec.json").read_text()) + import build_wide + t = build_wide.build(dict(spec)) + print(json.dumps({k: t.get(k) for k in ("instance_id", "gold_sites", "gold_site_files", "gold_files", + "gold_test_outcomes", "validation")}, indent=1)[:3000]) + + +def load_recipes() -> None: + """Recipes live in deep_recipes_.py, which register via @recipe.""" + for mod in ("deep_recipes_java", "deep_recipes_go", "deep_recipes_ts", "deep_recipes_py"): + try: + __import__(mod) + except ModuleNotFoundError as e: + if e.name != mod: + raise + + +def main(argv: list[str]) -> None: + load_recipes() + cmd = argv[1] + if cmd == "list": + for k, v in RECIPES.items(): + print(k, v["change"]) + elif cmd == "gold": + print(json.dumps(make_gold(argv[2]), indent=1)[:2000]) + elif cmd == "build": + build(argv[2]) + + +if __name__ == "__main__": + import build_deep # one module instance: recipes register into build_deep.RECIPES + build_deep.main(sys.argv) diff --git a/harness/build/build_wide.py b/harness/build/build_wide.py index 89271110..3ae38b0d 100644 --- a/harness/build/build_wide.py +++ b/harness/build/build_wide.py @@ -87,6 +87,8 @@ def build(spec: dict, dry: bool = False) -> dict: repo = wide_eval.repo_dir(task) if task.get("site_mode") == "files": return _build_files_mode(task, gold, repo, dry) + if task.get("site_mode") == "shapes": + return _build_shapes_mode(task, gold, repo, dry) base_wt = wide_eval._checkout(repo, task["base_commit"], "") gold_wt = wide_eval._checkout(repo, task["base_commit"], gold) try: @@ -168,8 +170,73 @@ def _build_files_mode(task: dict, gold: str, repo: Path, dry: bool) -> dict: return task +def _build_shapes_mode(task: dict, gold: str, repo: Path, dry: bool) -> dict: + """Seeded deep change (add a required parameter, change a return type, + move a type): spec adds site_mode="shapes", shapes (wide_eval.shape_counts: + the OLD forms the change removes), optional test selection (test_classes / + test_functions / test_modules; defaults below) and optional partial_patch + (path to gold minus a few sites, which must NOT resolve). Every shape must + occur more often at base than at gold somewhere, or it guards nothing.""" + partial_path = task.pop("partial_patch", None) + gold_touched = sorted({l[6:] for l in gold.splitlines() if l.startswith("+++ b/")}) + task["gold_files"] = gold_touched + base_wt = wide_eval._checkout(repo, task["base_commit"], "") + gold_wt = wide_eval._checkout(repo, task["base_commit"], gold) + try: + task["base_shape_counts"] = wide_eval.shape_counts(base_wt, task["shapes"]) + task["gold_shape_counts"] = wide_eval.shape_counts(gold_wt, task["shapes"]) + finally: + shutil.rmtree(base_wt, ignore_errors=True) + shutil.rmtree(gold_wt, ignore_errors=True) + sites = {} + for s in task["shapes"]: + b, g = task["base_shape_counts"][s["id"]], task["gold_shape_counts"][s["id"]] + sites[s["id"]] = {f: n - g.get(f, 0) for f, n in b.items() if n > g.get(f, 0)} + if not sites[s["id"]]: + raise SystemExit(f"shape {s['id']} is not removed anywhere by gold") + task["gold_sites"] = sum(sum(v.values()) for v in sites.values()) + task["gold_site_files"] = len({f for v in sites.values() for f in v}) + tests = [f for f in gold_touched if TEST_PATH[task["lang"]].search(f)] + if task["lang"] == "java": + task.setdefault("test_classes", [_java_class(f) for f in tests if "src/test/java/" in f]) + elif task["lang"] == "go": + task.setdefault("test_functions", _go_test_funcs(repo, task["base_commit"], gold_touched)) + task.setdefault("test_modules", ["tests"] if task["lang"] == "python" else []) + res = run_gold_tests(task, gold, repo) + at_base = run_gold_tests(task, "", repo) + task["pass_to_pass"] = sorted(n for n, s in res.items() if s == "PASSED" and at_base.get(n) == "PASSED") + task["gold_test_outcomes"] = {"run": len(res), "passed": len(task["pass_to_pass"]), + "failed": sorted(n for n, s in res.items() if s != "PASSED")[:30]} + if not task["pass_to_pass"]: + raise SystemExit("no test passes with gold: the green layer would be empty") + val = {} + g = wide_eval.score(task, gold) + val["gold"] = {"resolved": g.get("resolved"), "sites_ok": g.get("sites_ok"), "green": g.get("green"), + "n_run": (g.get("tests") or {}).get("n_run")} + if not g.get("resolved"): + raise SystemExit(f"gold does not resolve under the scorer: {json.dumps(g)[:800]}") + # the empty diff is refused outright by score(); show the oracle itself rejects base too + e = wide_eval.shape_site_check(repo, task, "") + val["empty"] = {"resolved": wide_eval.score(task, "").get("resolved"), + "sites_ok": e["sites_ok"], "missed_sites": e["missed_sites"]} + if e["sites_ok"]: + raise SystemExit("the base tree passes the site oracle") + if partial_path: + part = Path(partial_path).read_text() + pr = wide_eval.score(task, part) + val["partial"] = {"resolved": pr.get("resolved"), "sites_ok": pr.get("sites_ok"), + "green": pr.get("green"), "missed_sites": (pr.get("sites") or {}).get("missed_sites"), + "n_run": (pr.get("tests") or {}).get("n_run")} + if pr.get("resolved"): + raise SystemExit("the partial patch resolves: the oracle cannot see a missed site") + task["validation"] = val + if not dry: + (H / "tasks/e2e" / f"{task['instance_id']}.json").write_text(json.dumps(task, indent=1)) + return task + + if __name__ == "__main__": spec = json.loads(Path(sys.argv[1]).read_text()) t = build(spec, dry="--dry-run" in sys.argv) print(json.dumps({k: t.get(k) for k in ("instance_id", "gold_sites", "wide_test_files", - "gold_test_outcomes")}, indent=1)) + "gold_test_outcomes", "gold_site_files", "validation")}, indent=1)) diff --git a/harness/build/deep_edit.py b/harness/build/deep_edit.py new file mode 100644 index 00000000..93465fe9 --- /dev/null +++ b/harness/build/deep_edit.py @@ -0,0 +1,183 @@ +"""Offset-preserving source editing helpers for seeded DEEP tasks. + +The gold patch of a deep task (build_wide.py site_mode="shapes") is made +mechanically: locate every declaration/call of a method in comment- and +string-masked text (same length as the source, so offsets carry over), +edit the raw text at those offsets, then let the compiler / test suite +confirm the result. These helpers are deliberately language-agnostic and +syntax-light; per-task recipes in build_deep.py decide which matches are +sites, and the language's build is the check. +""" +from __future__ import annotations + +import re +import subprocess +from dataclasses import dataclass +from pathlib import Path + +_OPEN, _CLOSE = "([{", ")]}" + + +def mask(text: str, path: str) -> str: + """Same-length copy of text with comments blanked and string-literal + bodies replaced by '0' (quotes kept), newlines preserved.""" + ext = Path(path).suffix + py = ext == ".py" + out = list(text) + i, n = 0, len(text) + + def blank(a, b, ch=" "): + for k in range(a, b): + if out[k] != "\n": + out[k] = ch + + while i < n: + c = text[i] + if py and c == "#": + j = text.find("\n", i) + j = n if j < 0 else j + blank(i, j) + i = j + continue + if not py and text.startswith("//", i): + j = text.find("\n", i) + j = n if j < 0 else j + blank(i, j) + i = j + continue + if not py and text.startswith("/*", i): + j = text.find("*/", i + 2) + j = n if j < 0 else j + 2 + blank(i, j) + i = j + continue + if c in "\"'`" and (py or c != "`" or ext not in (".py",)): + if py and c == "`": + i += 1 + continue + if not py and c == "'" and ext in (".go", ".java", ".kt"): + j = i + 1 + while j < n and text[j] != "'" and text[j] != "\n": + j += 2 if text[j] == "\\" else 1 + blank(i + 1, j, "0") + i = j + 1 + continue + if py and text[i:i + 3] in ('"""', "'''"): + q = text[i:i + 3] + elif not py and c == '"' and text.startswith('"""', i) and ext in (".java", ".kt"): + q = '"""' + else: + q = c + j = i + len(q) + while j < n and not text.startswith(q, j): + if text[j] == "\\" and not (c == "`" and ext == ".go"): + j += 2 + continue + if text[j] == "\n" and q in ('"', "'") and not py: + break + if text[j] == "\n" and q in ('"', "'") and py: + break + j += 1 + blank(i + len(q), min(j, n), "0") + i = j + len(q) + continue + i += 1 + return "".join(out) + + +@dataclass +class Call: + name_start: int + name_end: int + open: int # index of "(" + close: int # index of matching ")" + args: list # [(start, end)] spans of top-level args, raw offsets, stripped of whitespace + + @property + def arity(self) -> int: + return len(self.args) + + +def find_calls(raw: str, masked: str, name: str) -> list[Call]: + res = [] + for m in re.finditer(rf"(?()]*(?:<[^<>()]*>[^<>()]*)*>)?\s*\(", masked): + op = m.end() - 1 + depth, i, start, args = 1, op + 1, op + 1, [] + while i < len(masked) and depth: + ch = masked[i] + if ch in _OPEN: + depth += 1 + elif ch in _CLOSE: + depth -= 1 + if not depth: + break + elif ch == "," and depth == 1: + args.append((start, i)) + start = i + 1 + i += 1 + args.append((start, i)) + spans = [] + for a, b in args: + seg = masked[a:b] + if seg.strip(): + lead = len(seg) - len(seg.lstrip()) + trail = len(seg) - len(seg.rstrip()) + spans.append((a + lead, b - trail)) + res.append(Call(m.start(), m.start() + len(name), op, i, spans)) + return res + + +def prev_token(masked: str, pos: int) -> str: + """The identifier/punctuation token immediately before pos (skipping spaces).""" + j = pos - 1 + while j >= 0 and masked[j].isspace(): + j -= 1 + if j < 0: + return "" + if masked[j].isalnum() or masked[j] in "_$": + k = j + while k >= 0 and (masked[k].isalnum() or masked[k] in "_$"): + k -= 1 + return masked[k + 1:j + 1] + return masked[j] + + +def next_char(masked: str, pos: int) -> str: + j = pos + while j < len(masked) and masked[j].isspace(): + j += 1 + return masked[j] if j < len(masked) else "" + + +def apply_edits(raw: str, edits: list[tuple[int, int, str]]) -> str: + """edits: (start, end, replacement); applied right to left; must not overlap.""" + for a, b, rep in sorted(edits, key=lambda e: (e[0], e[1]), reverse=True): + raw = raw[:a] + rep + raw[b:] + return raw + + +def insert_arg(raw: str, call: Call, index: int, expr: str) -> tuple[int, int, str]: + """An edit inserting expr as argument #index (0-based; == arity appends).""" + if call.arity == 0: + return (call.open + 1, call.close, expr) + if index >= call.arity: + end = call.args[-1][1] + return (end, end, ", " + expr) + start = call.args[index][0] + return (start, start, expr + ", ") + + +def enclosing_text(raw: str, pos: int, back: int = 6000) -> str: + return raw[max(0, pos - back):pos] + + +def git(*a, cwd=None, check=True) -> str: + r = subprocess.run(["git", *a], cwd=cwd, capture_output=True, text=True) + if check and r.returncode != 0: + raise RuntimeError(r.stderr[-500:]) + return r.stdout + + +def code_files(root: Path, exts: tuple[str, ...]) -> list[str]: + return [f for f in git("-C", str(root), "ls-files").splitlines() + if f.endswith(exts) and not re.search(r"(^|/)(node_modules|vendor|dist|build|target)/", f)] diff --git a/harness/build/deep_recipes_go.py b/harness/build/deep_recipes_go.py new file mode 100644 index 00000000..be32bf2b --- /dev/null +++ b/harness/build/deep_recipes_go.py @@ -0,0 +1,458 @@ +"""Go recipes for build_deep.py (gin, echo, urfave/cli ...). + +Gold = declarations by pattern, then the Go compiler's own errors +(`go build` + `go test -run ^$` compile of every package, -gcflags=-e so +every error prints, once per build-tag set) drive the call-site edits, +iterated to a clean build; gofmt on changed files.""" +from __future__ import annotations + +import os +import re +import subprocess +from pathlib import Path + +import build_deep as bd +from build_deep import recipe, read, write +import deep_edit as de + +GO = "/opt/homebrew/opt/go@1.25/bin/go" +GOFMT = "/opt/homebrew/opt/go@1.25/bin/gofmt" + +GIN = bd.CORPUS / "gin" +GIN_BASE = "d75fcd4c9ab260e5225de590f1f0f8c0e0e12d11" +ECHO = bd.CORPUS / "echo" +ECHO_BASE = "3d084be9022432c5a5257924c7d74bfc3444b456" +CLI = bd.CORPUS / "cli" +CLI_BASE = "58ec406eff149315193d8632c08317f70f6deee1" + +GO_ERR = re.compile(r"^(?:\.\/)?([\w./-]+\.go):(\d+):(\d+): (.*)$", re.M) + + +def go_env(): + env = dict(os.environ, GOTOOLCHAIN="local", GOFLAGS="-mod=mod") + env["PATH"] = str(Path(GO).parent) + ":" + env["PATH"] + return env + + +def go_compile(wt: Path, tags: list[str]) -> tuple[bool, list, str]: + """Compile every package and every test binary; (ok, [(file, line, col, msg)], output).""" + errs, outs, ok = [], [], True + for tag in tags: + tg = ["-tags", tag] if tag else [] + for cmd in ([GO, "build", "-gcflags=-e", *tg, "./..."], + [GO, "test", "-count=1", "-run", "^$", "-gcflags=-e", "-vet=off", *tg, "./..."]): + r = subprocess.run(cmd, cwd=wt, capture_output=True, text=True, env=go_env(), timeout=1800) + out = r.stdout + r.stderr + outs.append(out) + if r.returncode != 0: + ok = False + for m in GO_ERR.finditer(out): + f = m.group(1) + if not (wt / f).exists(): + continue # paths are cwd-relative for ./... builds + errs.append((f, int(m.group(2)), int(m.group(3)), m.group(4))) + seen, uniq = set(), [] + for e in errs: + if e not in seen: + seen.add(e) + uniq.append(e) + return ok, uniq, "\n".join(outs)[-4000:] + + +def gofmt(wt: Path) -> None: + changed = [l[3:] for l in de.git("-C", str(wt), "status", "--porcelain").splitlines() + if l[3:].endswith(".go")] + if changed: + subprocess.run([GOFMT, "-w", *changed], cwd=wt, check=True) + + +def go_files(wt: Path) -> list[str]: + return de.code_files(wt, (".go",)) + + +def call_at(wt: Path, f: str, name: str, line: int, col: int, arity: int | None = None): + """The innermost call of `name` whose span contains (line, col), or whose + name starts on that line.""" + raw = read(wt, f) + off = bd.line_offset(raw, line, col) + m = de.mask(raw, f) + best = None + after = None + for c in de.find_calls(raw, m, name): + if arity is not None and c.arity != arity: + continue + if c.name_start <= off <= c.close or raw.count("\n", 0, c.name_start) + 1 == line: + if best is None or c.name_start > best.name_start: + best = c + elif c.name_start > off and (after is None or c.name_start < after.name_start): + after = c # go reports a call at the start of its receiver expression + best = best or after + return raw, m, best + + +def compile_until_clean(wt: Path, tags: list[str], fix_error, rounds: int = 10) -> None: + last = None + for i in range(rounds): + ok, errs, tail = go_compile(wt, tags) + print(f" go compile round {i}: ok={ok} errors={len(errs)}", flush=True) + if ok: + return + if not errs: + raise RuntimeError("build failed without parsable errors:\n" + tail) + if sorted(errs) == last: + raise RuntimeError("no progress:\n" + "\n".join(map(str, errs[:30]))) + last = sorted(errs) + handled = 0 + done_files_lines = set() + for e in sorted(errs, key=lambda e: (e[0], -e[1], -e[2])): + if (e[0], e[1], e[2]) in done_files_lines: + continue + if fix_error(*e): + handled += 1 + done_files_lines.add((e[0], e[1], e[2])) + if not handled: + raise RuntimeError("unhandled errors:\n" + "\n".join(map(str, errs[:40]))) + raise RuntimeError("did not converge") + + +def enclosing_go_func(masked: str, pos: int) -> int: + """Offset of the `func` keyword of the innermost top-level func declaration before pos.""" + starts = [m.start() for m in re.finditer(r"(?m)^func\b", masked[:pos])] + return starts[-1] if starts else 0 + + +def add_param_to_decls(wt: Path, name: str, old_arity: int, is_decl, param: str, + files_filter=lambda f: True) -> int: + """Append `param` to every declaration (is_decl(raw, masked, call, file) True).""" + n = 0 + for f in go_files(wt): + if not files_filter(f): + continue + raw = read(wt, f) + if name not in raw: + continue + m = de.mask(raw, f) + edits = [] + for c in de.find_calls(raw, m, name): + if c.arity == old_arity and is_decl(raw, m, c, f): + first = raw[c.args[0][0]:c.args[0][1]] if c.args else "x T" + unnamed = " " not in first.strip() # `Bind(*http.Request, any)` + edits.append(de.insert_arg(raw, c, old_arity, param.split()[-1] if unnamed else param)) + if edits: + write(wt, f, de.apply_edits(raw, edits)) + n += len(edits) + return n + + +def is_method_decl(raw: str, masked: str, c, f: str) -> bool: + """`func (recv) Name(` or an interface method line `\tName(`.""" + line_start = masked.rfind("\n", 0, c.name_start) + 1 + head = masked[line_start:c.name_start] + return bool(re.fullmatch(r"func\s*\([^()]*\)\s*", head) or re.fullmatch(r"\s+", head)) + + +# ------------------------------------------------------------------ G1 gin Binding.Bind + +GIN_BIND_INSTR = ( + "Request bindings always validate with the package-level `binding.Validator`, so a caller cannot " + "choose another validator per call. Make the validator explicit: add a third, required parameter " + "`v StructValidator` to the `Bind` method of the `binding.Binding` interface (binding/binding.go and " + "its `nomsgpack` twin binding/binding_nomsgpack.go), so it becomes " + "`Bind(req *http.Request, obj any, v StructValidator) error`. Change every implementation " + "(jsonBinding, xmlBinding, formBinding, formPostBinding, formMultipartBinding, queryBinding, " + "headerBinding, plainBinding, protobufBinding, msgpackBinding, yamlBinding, tomlBinding, " + "bsonBinding, and any implementation in tests) and every call of `Binding.Bind`, in source and in " + "tests (including tests built only with the `nomsgpack` tag). Every existing call must pass the " + "package-level validator, so behavior does not change: `binding.Validator` outside package " + "binding (e.g. `Context.ShouldBindWith`), `Validator` inside it. Implementations do not have to " + "use the new parameter yet. Do not add a two-argument variant. Do not change `Context.Bind(obj)`, " + "the `gin.Bind` helper, `BindingBody.BindBody`, `BindingUri.BindUri` or any other `Bind*` method." +) + + +@recipe(instance_id="deep__gin__Binding_Bind_add_validator", + repo="gin-gonic/gin", lang="go", repo_dir=GIN, base_commit=GIN_BASE, + change="add required parameter (interface method: 13 implementations + callers, two build-tag variants)", + instruction=GIN_BIND_INSTR, + decl_files=["binding/binding.go", "binding/binding_nomsgpack.go"], + shapes=[{"id": "Bind/2", "name": "Bind", "arity": 2}], + gold_tool="build_deep.py go recipe: declarations by pattern (func (recv) Bind(req *http.Request, obj any) " + "and the interface lines), call sites from go build/go test compile errors (-gcflags=-e, default " + "tags and -tags nomsgpack), iterated to a clean build; gofmt (go1.25.14 GOTOOLCHAIN=local)", + notes="Look-alikes: Context.Bind(obj), gin.Bind(val) (arity 1), BindBody/BindUri (other names).") +def make_gin_bind(wt: Path): + def is_decl(raw, m, c, f): + if not f.startswith("binding/") or f.endswith("_test.go"): + return is_method_decl(raw, m, c, f) and "*http.Request" in raw[c.open:c.close] + return is_method_decl(raw, m, c, f) + n = add_param_to_decls(wt, "Bind", 2, is_decl, "v StructValidator") + print(f" declarations: {n}") + + def fix(f, line, col, msg): + if not re.search(r"(not enough arguments in call to .*\bBind\b)", msg): + return False + raw, m, c = call_at(wt, f, "Bind", line, col, arity=2) + if c is None: + return False + pkg = re.search(r"(?m)^package\s+(\w+)", raw).group(1) + val = "Validator" if pkg == "binding" else "binding.Validator" + write(wt, f, de.apply_edits(raw, [de.insert_arg(raw, c, 2, val)])) + return True + + compile_until_clean(wt, ["", "nomsgpack"], fix) + gofmt(wt) + + +# ------------------------------------------------------------------ G2 echo MiddlewareConfigurator.ToMiddleware + +ECHO_TOMW_INSTR = ( + "Middleware configurations are turned into middleware without knowing which Echo instance they will " + "serve. Add a required parameter `e *Echo` to the `ToMiddleware` method of the " + "`echo.MiddlewareConfigurator` interface (echo.go), so it becomes " + "`ToMiddleware(e *Echo) (MiddlewareFunc, error)`, and change every configuration type that " + "implements it (every `XxxConfig.ToMiddleware` in the middleware package, as " + "`ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error)`) and every call of `ToMiddleware`, in " + "source and in tests. At each call pass the `*echo.Echo` the middleware is being built for when the " + "calling function has one in scope (in tests this is usually the `e := echo.New()` instance); where " + "there is none (e.g. `toMiddlewareOrPanic`, used by the `XxxWithConfig` constructors, and tests " + "that build middleware without an Echo instance) pass `nil`. Implementations do not have to use the " + "parameter yet and must accept `nil`. Do not keep a parameterless variant. Behavior must not change." +) + + +@recipe(instance_id="deep__echo__MiddlewareConfigurator_ToMiddleware_add_echo", + repo="labstack/echo", lang="go", repo_dir=ECHO, base_commit=ECHO_BASE, + change="add required parameter (interface method: 22 middleware config implementations + callers)", + instruction=ECHO_TOMW_INSTR, + decl_files=["echo.go"], + shapes=[{"id": "ToMiddleware/0", "name": "ToMiddleware", "arity": 0}], + gold_tool="build_deep.py go recipe: declarations by pattern (func (config XxxConfig) ToMiddleware() and the " + "interface line), call sites from go build/go test compile errors (-gcflags=-e), " + "iterated to a clean build; gofmt (go1.25.14 GOTOOLCHAIN=local)", + notes="Call-site value: the enclosing function's `e := echo.New()` when present, else nil.") +def make_echo_tomw(wt: Path): + def param_for(f): + return "e *Echo" if not f.startswith("middleware/") else "e *echo.Echo" + n = 0 + for f in go_files(wt): + raw = read(wt, f) + if "ToMiddleware" not in raw: + continue + m = de.mask(raw, f) + edits = [de.insert_arg(raw, c, 0, param_for(f)) for c in de.find_calls(raw, m, "ToMiddleware") + if c.arity == 0 and is_method_decl(raw, m, c, f)] + if edits: + write(wt, f, de.apply_edits(raw, edits)) + n += len(edits) + print(f" declarations: {n}") + + def fix(f, line, col, msg): + if not re.search(r"not enough arguments in call to .*\bToMiddleware\b", msg): + return False + raw, m, c = call_at(wt, f, "ToMiddleware", line, col, arity=0) + if c is None: + return False + body = m[enclosing_go_func(m, c.name_start):c.name_start] + val = "e" if re.search(r"(?m)^\s*e\s*:?=\s*echo\.New\(\)", body) or \ + re.search(r"(?m)^\s*e\s*:?=\s*New\(\)", body) else "nil" + write(wt, f, de.apply_edits(raw, [de.insert_arg(raw, c, 0, val)])) + return True + + compile_until_clean(wt, [""], fix) + gofmt(wt) + + +# ------------------------------------------------------------------ G3 urfave/cli ValueCreator.Create -> (Value, error) + +CLI_CREATE_INSTR = ( + "`ValueCreator.Create` (flag_impl.go) cannot report a bad default or config: it returns only a " + "`Value`. Change its return type to `(Value, error)`, so the interface method becomes " + "`Create(T, *T, C) (Value, error)`. Change every implementation (boolValue, durationValue, " + "floatValue, genericValue, intValue, uintValue, stringValue, textValue, timestampValue, MapBase, " + "SliceBase and any other) to the new signature; the existing implementations never fail and return " + "a nil error. Update every caller, in source and in tests, to handle the error: where the calling " + "function returns an error, return it (`ArgumentBase.Parse`, `ArgumentsBase.Parse`, " + "`FlagBase.PreParse`, and `MapBase.Create` / `SliceBase.Create`, which call the element creator); " + "in tests, fail the test on a non-nil error (`require.NoError`/`t.Fatal`), or panic inside helper " + "closures that have no `*testing.T`. Do not keep a single-result variant or wrapper. Do not touch " + "unrelated `Create` functions such as `os.Create`. Behavior must not change." +) + +CLI_SINGLE_USE = r"(?m)^\s*[\w.]+\s*:?=\s*[\w.]+\.Create\(|\b\w+:\s*[\w.]+\.Create\(" + + +@recipe(instance_id="deep__cli__ValueCreator_Create_return_error", + repo="urfave/cli", lang="go", repo_dir=CLI, base_commit=CLI_BASE, + change="change return type T -> (T, error) (generic interface method: 12 implementations + callers " + "that must restructure expression uses into error handling)", + instruction=CLI_CREATE_INSTR, + decl_files=["flag_impl.go"], + shapes=[{"id": "Create/returns-Value", "regex": r"\bCreate\s*\([^()]*\)\s*Value\b"}, + {"id": "Create/single-value-use", "regex": CLI_SINGLE_USE}], + gold_tool="build_deep.py go recipe: declarations by pattern (return type Value -> (Value, error), " + "`return x` -> `return x, nil` in their bodies), callers rewritten by explicit per-site edits, " + "go build + go test compile clean (go1.25.14 GOTOOLCHAIN=local); gofmt", + notes="Call sites are guarded by the compiler (a two-result call in single-value context does not " + "compile) and by the single-value-use regex shape.") +def make_cli_create(wt: Path): + # 1. callers inside the element-wrapping creators, before their own returns change + for f, typ in (("flag_map_impl.go", "MapBase"), ("flag_slice_base.go", "SliceBase")): + raw = read(wt, f) + pat = rf"\treturn &{typ}\[T, C, VC\]\{{(?=[^}}]*vc\.Create)" + raw, k = re.subn(pat, lambda mm: "\tvalue, err := vc.Create(t, np, c)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n" + + mm.group(0), raw) + assert k == 1, (f, k) + raw = re.sub(r"(value:\s*)vc\.Create\(t, np, c\),", r"\1value,", raw) + write(wt, f, raw) + # 2. interface + implementations + n = 0 + for f in go_files(wt): + raw = read(wt, f) + if "Create" not in raw: + continue + m = de.mask(raw, f) + edits = [] + for dm in re.finditer(r"(?m)^func\s*\([^()]*\)\s*Create\s*\([^()]*\)\s*(Value)\s*\{", m): + edits.append((dm.start(1), dm.end(1), "(Value, error)")) + # body: from the "{" to its match + i, depth = dm.end() - 1, 0 + while True: + depth += m[i] == "{" + depth -= m[i] == "}" + if depth == 0: + break + i += 1 + body_s, body_e = dm.end(), i + assert "func(" not in m[body_s:body_e], f + for rm in re.finditer(r"\breturn\b", m[body_s:body_e]): + j, d = body_s + rm.end(), 0 + while j < body_e: + ch = m[j] + if ch in "([{": + d += 1 + elif ch in ")]}": + d -= 1 + elif ch == "\n" and d == 0 and m[body_s + rm.end():j].strip() and m[j - 1] not in ",(": + break + j += 1 + expr = raw[body_s + rm.end():j].rstrip() + if expr.strip().startswith("nil, err"): + continue + end = body_s + rm.end() + len(expr) + edits.append((end, end, ", nil")) + n += 1 + im = re.search(r"(?m)^\s*Create\(T, \*T, C\) (Value)\s*$", m) + if im: + edits.append((im.start(1), im.end(1), "(Value, error)")) + n += 1 + if edits: + write(wt, f, de.apply_edits(raw, edits)) + print(f" declarations: {n}") + # 3. callers + subs = { + "args.go": [("\tvalue := vc.Create(a.Value, &t, a.Config)\n", + "\tvalue, err := vc.Create(a.Value, &t, a.Config)\n\tif err != nil {\n\t\treturn s, err\n\t}\n", 2)], + "flag_impl.go": [("\tif f.Destination == nil {\n\t\tf.value = f.creator.Create(newVal, new(T), f.Config)\n" + "\t} else {\n\t\tf.value = f.creator.Create(newVal, f.Destination, f.Config)\n\t}\n", + "\tdest := f.Destination\n\tif dest == nil {\n\t\tdest = new(T)\n\t}\n" + "\tvalue, err := f.creator.Create(newVal, dest, f.Config)\n\tif err != nil {\n\t\treturn err\n\t}\n" + "\tf.value = value\n", 1)], + "flag_int_test.go": [("\t\t\ttt.flag.Value = uValue.Create(u, &u, tt.config)\n", + "\t\t\tvalue, createErr := uValue.Create(u, &u, tt.config)\n\t\t\trequire.NoError(t, createErr)\n" + "\t\t\ttt.flag.Value = value\n", 1)], + "flag_uint_test.go": [("\t\t\ttt.flag.Value = uValue.Create(u, &u, tt.config)\n", + "\t\t\tvalue, createErr := uValue.Create(u, &u, tt.config)\n\t\t\trequire.NoError(t, createErr)\n" + "\t\t\ttt.flag.Value = value\n", 1)], + "flag_test.go": [("\tvar ipv int64\n\n\tf := &flag.Flag{\n\t\tName: \"bar\",\n\t\tUsage: \"bar usage\",\n" + "\t\tValue: iv.Create(11, &ipv, IntegerConfig{}),\n", + "\tvar ipv int64\n\n\tvalue, err := iv.Create(11, &ipv, IntegerConfig{})\n\trequire.NoError(t, err)\n\n" + "\tf := &flag.Flag{\n\t\tName: \"bar\",\n\t\tUsage: \"bar usage\",\n" + "\t\tValue: value,\n", 1)], + } + for f, reps in subs.items(): + raw = read(wt, f) + for old, new, cnt in reps: + assert raw.count(old) == cnt, (f, raw.count(old)) + raw = raw.replace(old, new) + write(wt, f, raw) + # schema-type test closures: func() *extFlag, no *testing.T of their own + f = "flag_schema_type_test.go" + raw = read(wt, f) + raw, k = re.subn(r"(?m)^(\t+)return &extFlag\{f: &flag\.Flag\{Value: (\w+\.Create\(.*\))\}\}\n", + lambda mm: f"{mm.group(1)}value, err := {mm.group(2)}\n{mm.group(1)}if err != nil {{\n" + f"{mm.group(1)}\tpanic(err)\n{mm.group(1)}}}\n" + f"{mm.group(1)}return &extFlag{{f: &flag.Flag{{Value: value}}}}\n", raw) + assert k == 5, k + write(wt, f, raw) + + def fix(f, line, col, msg): + return False + + compile_until_clean(wt, [""], fix, rounds=1) + gofmt(wt) + return {"partial_drop": [("flag_schema_type_test.go", "dv.Create"), ("flag_bool.go", None)]} + + +# ------------------------------------------------------------------ G4 echo NewHTTPError(code, message) -> (code, message, internal) + +ECHO_NHE_INSTR = ( + "`echo.NewHTTPError(code int, message string) *HTTPError` (httperror.go) cannot record the " + "underlying cause; callers chain `.Wrap(err)` afterwards, which allocates a second error. Add a " + "third, required parameter `internal error` so the function becomes " + "`NewHTTPError(code int, message string, internal error) *HTTPError`, storing it as the wrapped " + "error (what `Unwrap` returns). Update every call, in source and in tests: where the result of " + "`NewHTTPError(...)` is immediately wrapped with `.Wrap(x)`, pass `x` as the new argument and drop " + "the `.Wrap` call; everywhere else pass `nil`. Do not change `HTTPError.Wrap` itself, the " + "`HTTPError{...}` literals, or the predefined `Err*` values' use of `.Wrap`. Do not keep a " + "two-argument variant. Behavior must not change." +) + + +@recipe(instance_id="deep__echo__NewHTTPError_add_internal", + repo="labstack/echo", lang="go", repo_dir=ECHO, base_commit=ECHO_BASE, + change="add required parameter (package function; call sites that chain .Wrap(x) must fold x into the new argument)", + instruction=ECHO_NHE_INSTR, + decl_files=["httperror.go"], + shapes=[{"id": "NewHTTPError/2", "name": "NewHTTPError", "arity": 2}, + {"id": "NewHTTPError(...).Wrap", "regex": r"\bNewHTTPError\s*\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\)\s*\.Wrap\("}], + gold_tool="build_deep.py go recipe: every NewHTTPError call (unique name) gets `, nil`, or the argument of an " + "immediately chained .Wrap(x) (which is removed); go build + go test compile clean " + "(go1.25.14 GOTOOLCHAIN=local); gofmt", + notes="") +def make_echo_nhe(wt: Path): + name = "NewHTTPError" + n = 0 + for f in go_files(wt): + raw = read(wt, f) + if name not in raw: + continue + m = de.mask(raw, f) + edits = [] + for c in de.find_calls(raw, m, name): + if c.arity != 2: + continue + if m[max(0, c.name_start - 5):c.name_start] == "func ": + edits.append(de.insert_arg(raw, c, 2, "internal error")) + continue + after = re.match(r"\s*\.Wrap\s*\(", m[c.close + 1:]) + if after: + wc = [w for w in de.find_calls(raw, m, "Wrap") if w.name_start > c.close][0] + x = raw[wc.args[0][0]:wc.args[0][1]] + edits.append((c.args[-1][1], wc.close + 1, f", {x})")) + else: + edits.append(de.insert_arg(raw, c, 2, "nil")) + n += 1 + if edits: + raw = de.apply_edits(raw, edits) + if f == "httperror.go": + old = "\t\tCode: code,\n\t\tMessage: message,\n\t}\n" + assert raw.count(old) == 1 + raw = raw.replace(old, "\t\tCode: code,\n\t\tMessage: message,\n\t\terr: internal,\n\t}\n") + write(wt, f, raw) + print(f" call sites: {n}") + + def fix(f, line, col, msg): + return False + + compile_until_clean(wt, [""], fix, rounds=1) + gofmt(wt) diff --git a/harness/build/deep_recipes_java.py b/harness/build/deep_recipes_java.py new file mode 100644 index 00000000..61234c40 --- /dev/null +++ b/harness/build/deep_recipes_java.py @@ -0,0 +1,465 @@ +"""Java recipes for build_deep.py (jackson-databind, commons-lang, gson ...).""" +from __future__ import annotations + +import re +from pathlib import Path + +import build_deep as bd +from build_deep import recipe, read, write, java_compile, ensure_java_import +import deep_edit as de + +DATABIND = bd.CORPUS / "jackson-databind" +DATABIND_BASE = "25b2a221f9aa4107e455065a74635e209418cf55" + + +def java_files(wt: Path) -> list[str]: + return de.code_files(wt, (".java",)) + + +def compile_until_clean(wt: Path, fix_error, rounds: int = 8, ignore=lambda e: False) -> None: + """Compile; hand every error to fix_error(file, line, col, msg) -> bool + (True = handled). Stop when clean; raise when an error is unhandled or + a round makes no progress.""" + last = None + for i in range(rounds): + ok, errs, tail = java_compile(wt) + errs = [e for e in errs if not ignore(e)] + print(f" compile round {i}: ok={ok} errors={len(errs)}", flush=True) + if ok or (not errs and ignore is not None and "module not found" in tail): + return + if not errs: + raise RuntimeError("build failed without parsable errors:\n" + tail) + key = sorted(errs) + if key == last: + raise RuntimeError("no progress:\n" + "\n".join(map(str, errs[:20]))) + last = key + # bottom-up per file so earlier offsets stay valid + unhandled = [] + for e in sorted(errs, key=lambda e: (e[0], -e[1], -e[2])): + if not fix_error(*e): + unhandled.append(e) + if unhandled and len(unhandled) == len(errs): + raise RuntimeError("unhandled errors:\n" + "\n".join(map(str, unhandled[:30]))) + raise RuntimeError("did not converge") + + +# ------------------------------------------------------------------ J1 +# JsonFormatVisitable.acceptJsonFormatVisitor(visitor, typeHint) +# -> acceptJsonFormatVisitor(visitor, typeHint, SerializerProvider provider) + +SP = "com.fasterxml.jackson.databind.SerializerProvider" + +AJFV_INSTR = ( + "Format visitors currently fetch the active `SerializerProvider` back out of the visitor " + "(`visitor.getProvider()`), which is null for visitors built without one. Make it explicit: add a " + "third, required parameter `SerializerProvider provider` to " + "`JsonFormatVisitable.acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)` " + "(com.fasterxml.jackson.databind.jsonFormatVisitors), so the method becomes " + "`acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint, SerializerProvider provider)`. " + "This changes `JsonSerializer.acceptJsonFormatVisitor` and every serializer (and every other " + "`JsonFormatVisitable`) that overrides it, in main and test code. Update every call of this method " + "to pass the provider in effect at the call site: inside an `acceptJsonFormatVisitor` implementation " + "pass its own `provider` parameter on; where some other `SerializerProvider` is in scope (a method " + "parameter, or `this` inside a provider) pass that; otherwise pass `visitor.getProvider()` for the " + "visitor being handed over. Do not keep a two-argument overload or a default. Do not change the " + "unrelated `acceptJsonFormatVisitor(JavaType/Class type, JsonFormatVisitorWrapper visitor)` methods " + "of `ObjectMapper`, `ObjectWriter` and `DefaultSerializerProvider` (their parameter order is reversed). " + "Implementations do not have to use the new parameter yet; behavior must not change." +) + + +@recipe(instance_id="deep__jackson-databind__acceptJsonFormatVisitor_add_provider", + repo="FasterXML/jackson-databind", lang="java", repo_dir=DATABIND, base_commit=DATABIND_BASE, + change="add required parameter (interface method, ~45 overrides + callers)", + instruction=AJFV_INSTR, + decl_files=["src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitors/JsonFormatVisitable.java", + "src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java"], + shapes=[{"id": "ajfv/2", "name": "acceptJsonFormatVisitor", "arity": 2}], + gold_tool="build_deep.py recipe: declarations by pattern (first parameter JsonFormatVisitorWrapper), " + "call sites from javac's own errors in docker maven test-compile, iterated to a clean build", + notes="Look-alikes with the same name and arity: ObjectMapper/ObjectWriter/DefaultSerializerProvider " + "acceptJsonFormatVisitor(type, visitor); unchanged by gold, so they cancel in the shape counts.") +def make_ajfv(wt: Path): + name = "acceptJsonFormatVisitor" + ndecl = 0 + for f in java_files(wt): + raw = read(wt, f) + if name not in raw: + continue + m = de.mask(raw, f) + edits = [] + for c in de.find_calls(raw, m, name): + first = raw[c.args[0][0]:c.args[0][1]] if c.args else "" + if de.prev_token(m, c.name_start) == "void" and c.arity == 2 and \ + re.match(r"(final\s+)?JsonFormatVisitorWrapper\b", first): + edits.append(de.insert_arg(raw, c, 2, "SerializerProvider provider")) + if edits: + raw = de.apply_edits(raw, edits) + raw = ensure_java_import(raw, SP) + write(wt, f, raw) + ndecl += len(edits) + print(f" declarations: {ndecl}") + + def fix(f, line, col, msg): + if "cannot be applied to given types" in msg or "no suitable method found for acceptJsonFormatVisitor" in msg \ + or ("acceptJsonFormatVisitor" in msg and "cannot be applied" in msg): + cs = [c for c in bd.calls_near(wt, f, name, line) if c.arity == 2] + if not cs: + return False + raw = read(wt, f) + m = de.mask(raw, f) + c = cs[0] + params = bd.enclosing_java_params(raw, m, c.name_start) + pm = re.search(r"\bSerializerProvider\s+(\w+)", params) + first = raw[c.args[0][0]:c.args[0][1]] + loc = re.findall(r"\bSerializerProvider\s+(\w+)\s*=", m[max(0, c.name_start - 1500):c.name_start]) + if pm: + val = pm.group(1) + elif loc: + val = loc[-1] + elif re.search(r"class\s+\w+\s+extends\s+(Default)?SerializerProvider", raw) and \ + "SerializerProvider" in f: + val = "this" + elif re.fullmatch(r"[\w.]+", first): + val = f"{first}.getProvider()" + else: + return False + write(wt, f, de.apply_edits(raw, [de.insert_arg(raw, c, 2, val)])) + return True + if "is already defined in method acceptJsonFormatVisitor" in msg: + raw = read(wt, f) + off = bd.line_offset(raw, line) + eol = raw.index("\n", off) + ln = raw[off:eol] + mm = re.match(r"\s*(?:final\s+)?SerializerProvider\s+provider\s*=\s*visitor\.getProvider\(\);\s*$", ln) + if not mm: + return False + write(wt, f, raw[:off] + raw[eol + 1:]) + return True + return False + + compile_until_clean(wt, fix) + + +# ------------------------------------------------------------------ J2 +# JsonDeserializer.supportsUpdate(DeserializationConfig): Boolean -> OptBoolean + +OPTB = "com.fasterxml.jackson.annotation.OptBoolean" + +SU_INSTR = ( + "`JsonDeserializer.supportsUpdate(DeserializationConfig config)` (com.fasterxml.jackson.databind) " + "returns a tri-state `java.lang.Boolean` where `null` means \"unknown\"; callers have to remember the " + "null case (`ReferenceTypeDeserializer.deserialize(p, ctxt, reference)` calls `.equals` on it). " + "Change its return type to `com.fasterxml.jackson.annotation.OptBoolean`: `Boolean.TRUE` becomes " + "`OptBoolean.TRUE`, `Boolean.FALSE` becomes `OptBoolean.FALSE`, and `null` (unknown) becomes " + "`OptBoolean.DEFAULT`. The base declaration in `JsonDeserializer` and every deserializer that overrides " + "it must return `OptBoolean` (implementations that forward to another deserializer keep forwarding; " + "implementations that return a stored `Boolean` must convert it, e.g. with `OptBoolean.fromBoolean`). " + "Update every caller of `supportsUpdate` to work with the `OptBoolean` result, treating `DEFAULT` the way " + "it treated `null`. Leave fields and constructor parameters that hold a `Boolean` (such as " + "`JsonNodeDeserializer`'s `_supportsUpdates`) as they are. Do not keep a `Boolean`-returning variant. " + "Behavior must not change." +) + + +@recipe(instance_id="deep__jackson-databind__supportsUpdate_OptBoolean", + repo="FasterXML/jackson-databind", lang="java", repo_dir=DATABIND, base_commit=DATABIND_BASE, + change="change return type (Boolean -> OptBoolean) of an overridden method + adapt callers", + instruction=SU_INSTR, + decl_files=["src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java"], + shapes=[{"id": "Boolean supportsUpdate", "regex": r"\bBoolean\s+supportsUpdate\s*\("}, + {"id": "Boolean = supportsUpdate", "regex": r"\bBoolean\s+\w+\s*=\s*[\w.()]*supportsUpdate\s*\("}], + gold_tool="build_deep.py recipe: return types and return statements of every supportsUpdate override " + "rewritten by pattern; the two value-using callers rewritten; docker maven test-compile clean") +def make_supports_update(wt: Path): + n = 0 + for f in java_files(wt): + raw = read(wt, f) + if "supportsUpdate" not in raw: + continue + orig = raw + m = de.mask(raw, f) + edits = [] + for dm in re.finditer(r"\bBoolean(\s+supportsUpdate\s*\(\s*DeserializationConfig\s+\w+\s*\)\s*\{)", m): + edits.append((dm.start(), dm.start() + len("Boolean"), "OptBoolean")) + # method body: up to the matching close brace + i, depth = dm.end(), 1 + while depth: + depth += m[i] == "{" + depth -= m[i] == "}" + i += 1 + body_a, body_b = dm.end(), i - 1 + for rm in re.finditer(r"\breturn\s+([^;]+);", m[body_a:body_b]): + a, b = body_a + rm.start(1), body_a + rm.end(1) + expr = raw[a:b] + rep = {"Boolean.TRUE": "OptBoolean.TRUE", "Boolean.FALSE": "OptBoolean.FALSE", + "null": "OptBoolean.DEFAULT", "_supportsUpdates": "OptBoolean.fromBoolean(_supportsUpdates)"} + if expr in rep: + edits.append((a, b, rep[expr])) + elif re.fullmatch(r"\(_valueDeserializer == null\) \? null\s+: _valueDeserializer\.supportsUpdate\(config\)", expr): + edits.append((a, b, expr.replace("? null", "? OptBoolean.DEFAULT"))) + elif re.fullmatch(r"[\w.()!= ]+\?\s*(Boolean\.TRUE|Boolean\.FALSE|null)\s*:\s*(Boolean\.TRUE|Boolean\.FALSE|null)", expr): + cond, rest = expr.split("?", 1) + rest = re.sub(r"Boolean\.(TRUE|FALSE)", r"OptBoolean.\1", rest) + rest = re.sub(r"\bnull\b", "OptBoolean.DEFAULT", rest) + edits.append((a, b, cond + "?" + rest)) + elif re.fullmatch(r"[\w.]+\.supportsUpdate\(\w+\)", expr): + pass # forwarding: type follows + else: + raise RuntimeError(f"unhandled return in {f}: {expr}") + n += 1 + if edits: + raw = de.apply_edits(raw, edits) + raw = ensure_java_import(raw, OPTB) + # callers that use the value + raw = raw.replace( + " Boolean mayMerge = valueDeser.supportsUpdate(ctxt.getConfig());\n\n" + " if (mayMerge == null) {", + " OptBoolean mayMerge = valueDeser.supportsUpdate(ctxt.getConfig());\n\n" + " if (mayMerge == OptBoolean.DEFAULT) {") + raw = raw.replace("} else if (!mayMerge.booleanValue()) { // prevented", + "} else if (mayMerge == OptBoolean.FALSE) { // prevented") + raw = raw.replace( + " Boolean B = _valueDeserializer.supportsUpdate(ctxt.getConfig());\n" + " // if explicitly stated that merge won't work...\n" + " if (B.equals(Boolean.FALSE) || (_valueTypeDeserializer != null)) {", + " OptBoolean B = _valueDeserializer.supportsUpdate(ctxt.getConfig());\n" + " // if explicitly stated that merge won't work...\n" + " if ((B == OptBoolean.FALSE) || (_valueTypeDeserializer != null)) {") + if raw != orig: + if "OptBoolean" in raw: + raw = ensure_java_import(raw, OPTB) + write(wt, f, raw) + print(f" overrides rewritten: {n}") + ok, errs, tail = java_compile(wt) + if not ok: + raise RuntimeError("gold does not compile:\n" + "\n".join(map(str, errs[:30])) + tail[-1500:]) + + +# ------------------------------------------------------------------ J3 +# move com.fasterxml.jackson.databind.util.NameTransformer -> ...databind.introspect + +NT_OLD, NT_NEW = "com.fasterxml.jackson.databind.util.NameTransformer", \ + "com.fasterxml.jackson.databind.introspect.NameTransformer" + +NT_INSTR = ( + "`NameTransformer` (property-name transformation used by `@JsonUnwrapped`) lives in the grab-bag " + "`com.fasterxml.jackson.databind.util` package, although it belongs with the other property " + "introspection types. Move the class `com.fasterxml.jackson.databind.util.NameTransformer` " + "(including its nested classes) to the package `com.fasterxml.jackson.databind.introspect`, i.e. to " + "`src/main/java/com/fasterxml/jackson/databind/introspect/NameTransformer.java`, and delete it from " + "`util` completely: no deprecated subclass, alias or forwarding copy may remain in the old package. " + "Update every reference in main and test code so the project compiles: explicit imports, " + "fully-qualified references, classes that relied on being in the same package or on a " + "`com.fasterxml.jackson.databind.util.*` wildcard import, and imports that become redundant because " + "the user is now in the same package as the class. Keep every test class in its current package. " + "Do not rename anything; behavior must not change." +) + + +@recipe(instance_id="deep__jackson-databind__NameTransformer_move_package", + repo="FasterXML/jackson-databind", lang="java", repo_dir=DATABIND, base_commit=DATABIND_BASE, + change="move a widely used type to another package (old location removed)", + instruction=NT_INSTR, + decl_files=["src/main/java/com/fasterxml/jackson/databind/introspect/NameTransformer.java", + "src/main/java/com/fasterxml/jackson/databind/util/NameTransformer.java"], + shapes=[{"id": "old FQN", "regex": r"\bcom\.fasterxml\.jackson\.databind\.util\.NameTransformer\b"}, + {"id": "class decl", "regex": r"\bclass\s+NameTransformer\b"}], + gold_tool="build_deep.py recipe: git mv + package line; imports/FQNs rewritten by pattern; same-package " + "and util.* wildcard users given an explicit import; docker maven test-compile clean") +def make_nt_move(wt: Path): + old_p = "src/main/java/com/fasterxml/jackson/databind/util/NameTransformer.java" + new_p = "src/main/java/com/fasterxml/jackson/databind/introspect/NameTransformer.java" + de.git("-C", str(wt), "mv", old_p, new_p) + src = read(wt, new_p).replace("package com.fasterxml.jackson.databind.util;", + "package com.fasterxml.jackson.databind.introspect;", 1) + write(wt, new_p, src) + n = 0 + for f in java_files(wt): + if not f.startswith("src/"): + continue + raw = read(wt, f) + if "NameTransformer" not in raw: + continue + orig = raw + pkg = (re.search(r"^package\s+([\w.]+);", raw, re.M) or [None, ""])[1] + in_introspect = pkg == "com.fasterxml.jackson.databind.introspect" + if in_introspect: + raw = re.sub(rf"^import\s+{re.escape(NT_OLD)};\n", "", raw, flags=re.M) + else: + raw = re.sub(rf"^import\s+{re.escape(NT_OLD)};", f"import {NT_NEW};", raw, flags=re.M) + m = de.mask(raw, f) + # fully qualified uses in code (not imports, not comments) + edits = [(x.start(), x.end(), NT_NEW) for x in re.finditer(re.escape(NT_OLD), m) + if not m[max(0, x.start() - 7):x.start()].startswith("import")] + raw = de.apply_edits(raw, edits) + m = de.mask(raw, f) + uses_simple = re.search(r"(?): TypeAdapter (null = "not mine") +# -> Optional> + +GSON = bd.CORPUS / "gson" +GSON_BASE = "dae37cf0fe12235b76fb09f01118a0a8c8823f42" + +TAF_INSTR = ( + "`TypeAdapterFactory.create(Gson gson, TypeToken type)` (com.google.gson) signals \"this factory " + "does not handle the type\" by returning `null`, which every caller has to remember to check. Change " + "its return type to `java.util.Optional>`: a factory that does not handle the type " + "returns `Optional.empty()`, a factory that does returns the adapter wrapped in an `Optional` (use " + "`Optional.ofNullable` where the adapter expression itself may be null). Update the interface and " + "every implementation -- named classes and anonymous `new TypeAdapterFactory() { ... }` classes, in all " + "Maven modules (gson, extras, proto, test-shrinker, ...) and in tests -- changing only the `return` " + "statements that belong to `create` itself (not the `return null` inside a nested `TypeAdapter`'s " + "`read`/`write`). Update every caller of `create` (e.g. `Gson.getAdapter`, `Gson.getDelegateAdapter`, " + "`JsonAdapterAnnotationTypeAdapterFactory`, tests) to unwrap the `Optional` so that \"not handled\" is " + "treated exactly as `null` was. Do not add a nullable-returning variant. Behavior must not change." +) + + +def _own_returns(m: str, a: int, b: int) -> list[tuple[int, int]]: + """(start, end) of `return ...;` statements in m[a:b] (a method body) + that belong to that method: not inside a nested class body or lambda.""" + stack = [False] # foreign? + out = [] + i = a + while i < b: + ch = m[i] + if ch == "{": + j = i - 1 + while j > a and m[j].isspace(): + j -= 1 + foreign = stack[-1] + if m[j - 1:j + 1] == "->": + foreign = True + elif m[j] == ")": + # match back to "(" and look at what precedes it + depth, k = 0, j + while k > a: + depth += m[k] == ")" + depth -= m[k] == "(" + if depth == 0: + break + k -= 1 + before = m[max(a, k - 200):k] + if re.search(r"\bnew\s+[\w.]+\s*(<[^;{}()]*>)?\s*$", before): + foreign = True + else: + seg = m[max(a, i - 300):i] + seg = re.split(r"[;{}]", seg)[-1] + if re.search(r"\b(class|interface|enum|record)\s+\w+", seg): + foreign = True + stack.append(foreign) + elif ch == "}": + stack.pop() + elif not stack[-1] and m.startswith("return", i) and not (m[i - 1].isalnum() or m[i - 1] == "_") \ + and not (m[i + 6].isalnum() or m[i + 6] == "_"): + k = i + depth = 0 + while True: + c = m[k] + if c in "([{": + depth += 1 + elif c in ")]}": + depth -= 1 + elif c == ";" and depth == 0: + break + k += 1 + out.append((i, k + 1)) + i = k + i += 1 + return out + + +@recipe(instance_id="deep__gson__TypeAdapterFactory_create_Optional", + repo="google/gson", lang="java", repo_dir=GSON, base_commit=GSON_BASE, + change="change return type (nullable -> Optional) of an interface method: ~45 implementations + callers", + instruction=TAF_INSTR, + decl_files=["gson/src/main/java/com/google/gson/TypeAdapterFactory.java"], + shapes=[{"id": "TypeAdapter create(Gson", "regex": r"\bTypeAdapter\s*<\s*\w+\s*>\s+create\s*\(\s*(?:final\s+)?Gson\b"}], + gold_tool="build_deep.py recipe: create() declarations and their own return statements rewritten " + "(nested-class/lambda returns excluded by a brace scan); callers unwrapped with " + ".orElse(null) from javac errors; docker maven test-compile clean") +def make_taf(wt: Path): + decl = re.compile(r"\bTypeAdapter(\s*<\s*(\w+)\s*>)(\s+create\s*\(\s*(?:final\s+)?Gson\s+\w+\s*,\s*(?:final\s+)?TypeToken\s*<[^>]*>\s*\w+\s*\)\s*\{)") + ndecl = nret = 0 + for f in java_files(wt): + raw = read(wt, f) + if "create" not in raw or "TypeAdapter" not in raw: + continue + m = de.mask(raw, f) + edits = [] + for dm in decl.finditer(m): + tv = dm.group(2) + edits.append((dm.start(), dm.start(3), f"Optional>")) + body_a = dm.end() + i, depth = body_a, 1 + while depth: + depth += m[i] == "{" + depth -= m[i] == "}" + i += 1 + for ra, rb in _own_returns(m, body_a, i - 1): + expr_a = ra + len("return") + expr = raw[expr_a:rb - 1].strip() + ea = raw.index(expr, expr_a) + if expr == "null": + edits.append((ea, ea + len(expr), "Optional.empty()")) + elif expr.startswith("new ") and not expr.startswith("new ") is False and \ + re.fullmatch(r"new\s[^?]*", expr) and "?" not in expr: + edits.append((ea, ea + len(expr), f"Optional.of({expr})")) + else: + edits.append((ea, ea + len(expr), f"Optional.ofNullable({expr})")) + nret += 1 + ndecl += 1 + if edits: + raw = de.apply_edits(raw, edits) + raw = ensure_java_import(raw, "java.util.Optional") + write(wt, f, raw) + itf = "gson/src/main/java/com/google/gson/TypeAdapterFactory.java" + raw = read(wt, itf) + raw = raw.replace(" TypeAdapter create(Gson gson, TypeToken type);", + " Optional> create(Gson gson, TypeToken type);") + write(wt, itf, ensure_java_import(raw, "java.util.Optional")) + print(f" create declarations: {ndecl}, own returns: {nret}") + + def fix(f, line, col, msg): + if "incompatible types" in msg and "Optional" in msg: + cs = [c for c in bd.calls_near(wt, f, "create", line) if c.arity == 2] + if not cs: + return False + raw = read(wt, f) + c = cs[0] + write(wt, f, raw[:c.close + 1] + ".orElse(null)" + raw[c.close + 1:]) + return True + return False + + jpms = lambda e: e[0].startswith("test-jpms/") and "module not found: com.google.gson" in e[3] + compile_until_clean(wt, fix, ignore=jpms) + # a cast caller compiles against Optional but would ClassCastException at runtime + for f in java_files(wt): + raw = read(wt, f) + new = re.sub(r"\(TypeAdapter\) adapterFactory\.create\(gson, typeToken\);", + "(TypeAdapter) adapterFactory.create(gson, typeToken).orElse(null);", raw) + if new != raw: + write(wt, f, new) + ok, errs, tail = java_compile(wt) + if [e for e in errs if not jpms(e)] or (not ok and not errs): + raise RuntimeError("gold does not compile after cast fix:\n" + "\n".join(map(str, errs[:20]))) diff --git a/harness/build/deep_recipes_py.py b/harness/build/deep_recipes_py.py new file mode 100644 index 00000000..71c78484 --- /dev/null +++ b/harness/build/deep_recipes_py.py @@ -0,0 +1,405 @@ +"""Python recipes for build_deep.py (werkzeug, rich, flask). + +Python has no compiler, so each recipe edits by resolved call shape +(deep_edit offsets over masked text) and the repo's own test suite is the +check; build_wide's shapes oracle is the site check. +""" +from __future__ import annotations + +import ast +import re +from pathlib import Path + +import build_deep as bd +from build_deep import recipe, read, write +import deep_edit as de + +E2E = bd.CORPUS / "e2e-2026" +WERKZEUG_BASE = "1b00618e787f40dfb21eba29caf8f8be7c8e1d93" +RICH_BASE = "9d8f9a372cc5916fd4781fec207ced7ddac2f08f" +FLASK_BASE = "36e4a824f340fdee7ed50937ba8e7f6bc7d17f81" + + +def py_files(wt: Path) -> list[str]: + return de.code_files(wt, (".py",)) + + +def def_span(raw: str, name: str, cls: str | None = None) -> tuple[int, int]: + """(start, end) offsets of a top-level (or class-level) def incl. decorators + and the trailing blank lines.""" + tree = ast.parse(raw) + body = tree.body + if cls: + body = next(n for n in tree.body if isinstance(n, ast.ClassDef) and n.name == cls).body + node = next(n for n in body if isinstance(n, (ast.FunctionDef, ast.ClassDef)) and n.name == name) + lines = raw.splitlines(keepends=True) + first = min([node.lineno] + [d.lineno for d in getattr(node, "decorator_list", [])]) + start = sum(len(l) for l in lines[:first - 1]) + end_line = node.end_lineno + while end_line < len(lines) and not lines[end_line].strip(): + end_line += 1 + end = sum(len(l) for l in lines[:end_line]) + return start, end + + +# ------------------------------------------------------------------ werkzeug +# remove werkzeug.test.create_environ; inline EnvironBuilder(...).get_environ() + +CE_INSTR = ( + "`werkzeug.test.create_environ(*args, **kwargs)` is a thin wrapper that only builds an " + "`EnvironBuilder` and returns its environ, and having two spellings for the same thing confuses " + "users. Remove `create_environ` from `werkzeug.test` (delete the function; do not keep an alias " + "or a deprecated shim) and rewrite every use in the repository, tests included, as " + "`EnvironBuilder().get_environ()`, passing exactly the arguments the call passed " + "before (positional and keyword). Fix the imports of every module that used it: import " + "`EnvironBuilder` from `werkzeug.test` instead, without duplicating an existing import. " + "Test names stay as they are. Behavior must not change." +) + + +@recipe(instance_id="deep__werkzeug__create_environ_inline_remove", + repo="pallets/werkzeug", lang="python", repo_dir=E2E / "pallets__werkzeug", base_commit=WERKZEUG_BASE, + change="remove a helper function and inline its replacement at every call site (+ import fixes)", + instruction=CE_INSTR, + decl_files=["src/werkzeug/test.py"], + shapes=[{"id": "create_environ", "name": "create_environ"}], + test_modules=["tests"], + gold_tool="build_deep.py recipe: masked-text call finder (deep_edit) rewrites each create_environ(...) " + "call to EnvironBuilder(...).get_environ(); AST removes the def; import lines rewritten; " + "werkzeug's test suite in docker confirms", + notes="All callers are tests; the green layer is werkzeug's full suite.") +def make_create_environ(wt: Path): + f = "src/werkzeug/test.py" + raw = read(wt, f) + a, b = def_span(raw, "create_environ") + write(wt, f, raw[:a] + raw[b:]) + n = 0 + for f in py_files(wt): + raw = read(wt, f) + if "create_environ" not in raw: + continue + m = de.mask(raw, f) + edits = [] + for c in de.find_calls(raw, m, "create_environ"): + if de.prev_token(m, c.name_start) == "def": + continue + edits.append((c.name_start, c.name_end, "EnvironBuilder")) + edits.append((c.close + 1, c.close + 1, ".get_environ()")) + n += 1 + raw = de.apply_edits(raw, edits) + has_eb = re.search(r"^from werkzeug\.test import [^\n]*\bEnvironBuilder\b", raw, re.M) + if has_eb: + raw = re.sub(r"^from werkzeug\.test import create_environ\n", "", raw, flags=re.M) + else: + raw = re.sub(r"^from werkzeug\.test import create_environ$", "from werkzeug.test import EnvironBuilder", + raw, flags=re.M) + write(wt, f, raw) + left = re.findall(r"\bcreate_environ\b", de.mask(raw, f)) + if left: + raise RuntimeError(f"{f}: create_environ left after rewrite") + print(f" rewrote {n} calls") + # import order: EnvironBuilder sorts before the other werkzeug.test imports in + # some files; keep isort-clean ordering is not checked by tests, so leave as is. + return {} + + +# ------------------------------------------------------------------ flask +# add_url_rule(rule, endpoint=None, ...) -> add_url_rule(rule, endpoint, ...) + +AURU_INSTR = ( + "Flask silently derives a URL rule's endpoint from the view function's name when " + "`add_url_rule` is called without one, which hides endpoint collisions. Make the `endpoint` " + "parameter of `add_url_rule` required -- remove its `= None` default (keep the annotation " + "`str | None`; `route()` still hands over `None` when its decorator was given no endpoint) -- on " + "every declaration: `Scaffold.add_url_rule` (flask/sansio/scaffold.py), `App.add_url_rule` " + "(flask/sansio/app.py), `Blueprint.add_url_rule` and `BlueprintSetupState.add_url_rule` " + "(flask/sansio/blueprints.py). Then update every call of `add_url_rule` in the repository that " + "does not pass an endpoint (tests and type-check fixtures included): pass, as the second " + "positional argument or as `endpoint=`, the exact name Flask derived before -- the view " + "function's `__name__`, which for `SomeView.as_view(\"name\", ...)` is that `name`. Calls that " + "already pass an endpoint stay as they are. Do not change `route()`'s signature or anything else; " + "behavior must not change." +) + + +def _flask_endpoint(raw: str, call: "de.Call") -> str | None: + for a, b in call.args: + arg = raw[a:b] + mm = re.match(r"view_func\s*=\s*(.*)$", arg, re.S) + if not mm: + continue + expr = mm.group(1).strip() + av = re.match(r"[\w.]+\.as_view\(\s*([\"'])([^\"']+)\1", expr) + if av: + return av.group(2) + if re.fullmatch(r"self\.\w+", expr): + return expr.split(".")[1] + if re.fullmatch(r"\w+", expr): + prior = raw[:call.name_start] + assigns = list(re.finditer(rf"^\s*{expr}\s*=\s*[\w.]+\.as_view\(\s*([\"'])([^\"']+)\1", prior, re.M)) + defs = list(re.finditer(rf"^\s*(?:async\s+)?def\s+{expr}\s*\(", prior, re.M)) + last_a = assigns[-1].start() if assigns else -1 + last_d = defs[-1].start() if defs else -1 + if last_a > last_d: + return assigns[-1].group(2) + if last_d >= 0: + return expr + return None + return None + + +@recipe(instance_id="deep__flask__add_url_rule_endpoint_required", + repo="pallets/flask", lang="python", repo_dir=E2E / "pallets__flask", base_commit=FLASK_BASE, + change="make a defaulted parameter required (4 declarations); callers must pass the derived value", + instruction=AURU_INSTR, + decl_files=["src/flask/sansio/scaffold.py", "src/flask/sansio/app.py", "src/flask/sansio/blueprints.py"], + shapes=[{"id": "auru/2", "name": "add_url_rule", "arity": 2}, + {"id": "auru/3", "name": "add_url_rule", "arity": 3}, + {"id": "endpoint=None", "regex": r"\bendpoint:\s*str\s*\|\s*None\s*=\s*None"}], + test_modules=["tests"], + gold_tool="build_deep.py recipe: declarations by pattern; every add_url_rule call without an " + "endpoint found with the masked-text call finder (deep_edit), endpoint resolved from " + "view_func (def name, as_view(name), or the as_view assignment it names); flask test suite " + "in docker confirms", + notes="Shapes: calls of add_url_rule by argument count (a call missing its endpoint keeps a " + "lower count than gold), plus the `endpoint: str | None = None` default on declarations. " + "Calls that already passed an endpoint are identical in base and gold, so they cancel.") +def make_auru(wt: Path): + n = nd = 0 + for f in py_files(wt): + raw = read(wt, f) + if "add_url_rule" not in raw: + continue + m = de.mask(raw, f) + edits = [] + for c in de.find_calls(raw, m, "add_url_rule"): + if de.prev_token(m, c.name_start) == "def": + seg = raw[c.open:c.close] + mm = re.search(r"\bendpoint:\s*str\s*\|\s*None\s*=\s*None", seg) + if mm: + a = c.open + mm.start() + edits.append((a, c.open + mm.end(), "endpoint: str | None")) + nd += 1 + continue + args = [raw[a:b] for a, b in c.args] + positional = [x for x in args if not re.match(r"\*{0,2}\w+\s*=|\*\*", x) and not x.startswith("*")] + has_kw = any(re.match(r"endpoint\s*=", x) for x in args) + if len(positional) >= 2 or has_kw or any(x.startswith("**") for x in args) and len(positional) >= 2: + continue + ep = _flask_endpoint(raw, c) + if ep is None: + raise RuntimeError(f"{f}:{raw.count(chr(10), 0, c.name_start) + 1}: cannot resolve endpoint: " + f"{raw[c.name_start:c.close + 1]}") + edits.append(de.insert_arg(raw, c, 1, f'"{ep}"')) + n += 1 + if edits: + write(wt, f, de.apply_edits(raw, edits)) + print(f" declarations {nd}, calls {n}") + if nd != 4: + raise RuntimeError(f"expected 4 declarations, got {nd}") + return {} + + +# ------------------------------------------------------------------ rich +# move class Measurement: rich.measure -> new module rich.measurement + +MEAS_INSTR = ( + "`rich/measure.py` mixes the `Measurement` value type with the `measure_renderables` helper. Move " + "the `Measurement` class (unchanged, with all its methods) into a new module `rich/measurement.py`, " + "and delete it from `rich/measure.py`; `measure_renderables` stays in `rich.measure` (which may " + "import `Measurement` from the new module for its own use). Then update every import of " + "`Measurement` in the repository -- the `rich` package, tests, benchmarks, examples and tools -- to " + "import it from the new module (`from .measurement import Measurement` inside the package, " + "`from rich.measurement import Measurement` elsewhere); where one import line brings in both " + "`Measurement` and `measure_renderables`, split it so `measure_renderables` still comes from " + "`rich.measure`. No module may keep importing `Measurement` from `rich.measure`. Behavior must not " + "change and no circular import may be introduced." +) + +_MEAS_HEAD = '''from typing import TYPE_CHECKING, Callable, NamedTuple, Optional + +from . import errors +from .protocol import is_renderable, rich_cast + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderableType + + +''' + +_MEASURE_HEAD = '''from operator import itemgetter +from typing import TYPE_CHECKING, Sequence + +from .measurement import Measurement + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderableType + + +''' + + +@recipe(instance_id="deep__rich__Measurement_move_module", + repo="Textualize/rich", lang="python", repo_dir=E2E / "Textualize__rich", base_commit=RICH_BASE, + change="move a class to a new module, old location removed; every import updated (some split)", + instruction=MEAS_INSTR, + decl_files=["rich/measure.py", "rich/measurement.py"], + shapes=[{"id": "import-from-measure", + "regex": r"^[ \t]*from[ \t]+(?:rich\.|\.)measure[ \t]+import\b[^\n]*\bMeasurement\b"}, + {"id": "class-def", "regex": r"^class Measurement\b"}], + test_modules=["tests"], + gold_tool="build_deep.py recipe: class body moved by source span; import lines rewritten " + "(split where they also import measure_renderables); rich's test suite in docker confirms", + notes="Shapes: an import of Measurement from rich.measure (code, not strings/docstrings) and a " + "`class Measurement` left in rich/measure.py. rich.measure still binds Measurement (it " + "imports it for measure_renderables), so a missed import does not fail any test: the " + "shape oracle alone catches it.") +def make_meas(wt: Path): + raw = read(wt, "rich/measure.py") + a = raw.index("class Measurement(NamedTuple):") + b = raw.index("def measure_renderables(") + write(wt, "rich/measurement.py", _MEAS_HEAD + raw[a:b].rstrip() + "\n") + write(wt, "rich/measure.py", _MEASURE_HEAD + raw[b:]) + n = 0 + pat = re.compile(r"^([ \t]*)from[ \t]+(rich\.|\.)measure[ \t]+import[ \t]+([^\n(]+)$", re.M) + for f in py_files(wt): + if f == "rich/measure.py": + continue + raw = read(wt, f) + if "measure" not in raw: + continue + + def rep(m): + nonlocal n + ind, pfx, names = m.group(1), m.group(2), [x.strip() for x in m.group(3).split(",")] + if "Measurement" not in names: + return m.group(0) + n += 1 + rest = [x for x in names if x != "Measurement"] + out = [] + if rest: + out.append(f"{ind}from {pfx}measure import {', '.join(rest)}") + out.append(f"{ind}from {pfx}measurement import Measurement") + return "\n".join(out) + new = pat.sub(rep, raw) + if new != raw: + write(wt, f, new) + print(f" rewrote {n} imports") + return {"partial_drop": [("rich/table.py", "Measurement"), ("tests/test_text.py", "Measurement")]} + + +# ------------------------------------------------------------------ rich +# loop_first/loop_last/loop_first_last (flag(s) first) -> iter_first/iter_last/ +# iter_first_last (value first): a return-shape change every consumer must adapt to + +LOOP_INSTR = ( + "The iteration helpers in `rich/_loop.py` put the flag before the value -- `loop_first` and " + "`loop_last` yield `(is_first, value)` / `(is_last, value)` and `loop_first_last` yields " + "`(is_first, is_last, value)` -- the opposite of `enumerate`-style helpers, which keeps causing " + "unpacking mistakes. Change what they yield so the value comes first: `(value, is_first)`, " + "`(value, is_last)` and `(value, is_first, is_last)`, and rename them to `iter_first`, `iter_last` " + "and `iter_first_last` (no aliases under the old names) so no caller can silently keep the old " + "order. Update every use in the repository -- every import, every `for` loop that unpacks them, " + "and every place that consumes one of these iterators indirectly (for example an iterator pushed " + "on a stack and unpacked later with `next(...)`) -- and the tests of the helpers themselves. " + "Code that merely contains these names inside string literals (such as syntax-highlighting " + "fixtures) is not a use and must not change. Behavior must not change." +) + +_LOOP_RENAME = {"loop_first_last": "iter_first_last", "loop_first": "iter_first", "loop_last": "iter_last"} + + +def _split_top(s: str) -> list[str]: + out, depth, cur = [], 0, "" + for ch in s: + if ch in "([{": + depth += 1 + elif ch in ")]}": + depth -= 1 + if ch == "," and depth == 0: + out.append(cur.strip()) + cur = "" + else: + cur += ch + out.append(cur.strip()) + return out + + +@recipe(instance_id="deep__rich__loop_helpers_value_first", + repo="Textualize/rich", lang="python", repo_dir=E2E / "Textualize__rich", base_commit=RICH_BASE, + change="change return shape (yielded tuple order) + rename; every consumer's unpacking must adapt", + instruction=LOOP_INSTR, + decl_files=["rich/_loop.py"], + shapes=[{"id": "loop_first", "name": "loop_first"}, {"id": "loop_last", "name": "loop_last"}, + {"id": "loop_first_last", "name": "loop_first_last"}], + test_modules=["tests"], + gold_tool="build_deep.py recipe: masked-text rename of the three helpers; each `for` target list " + "that unpacks them reordered by parsing its top-level targets; the indirect consumer in " + "rich/tree.py and tests/test_tools.py edited by exact replacement; rich's suite in docker " + "confirms", + notes="Shapes catch a call/import left under an old name. A consumer renamed but not reordered is " + "caught only by the tests (rich's rendering tests exercise these loops heavily, but not " + "every one is guaranteed).") +def make_loop(wt: Path): + # the helpers themselves + f = "rich/_loop.py" + raw = read(wt, f) + raw = raw.replace("def loop_first(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:", + "def iter_first(values: Iterable[T]) -> Iterable[Tuple[T, bool]]:") + raw = raw.replace("def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:", + "def iter_last(values: Iterable[T]) -> Iterable[Tuple[T, bool]]:") + raw = raw.replace("def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]:", + "def iter_first_last(values: Iterable[T]) -> Iterable[Tuple[T, bool, bool]]:") + for old, new in [("yield True, value", "yield value, True"), ("yield False, value", "yield value, False"), + ("yield False, previous_value", "yield previous_value, False"), + ("yield True, previous_value", "yield previous_value, True"), + ("yield first, False, previous_value", "yield previous_value, first, False"), + ("yield first, True, previous_value", "yield previous_value, first, True")]: + assert old in raw, old + raw = raw.replace(old, new) + write(wt, f, raw) + n_for = 0 + for f in py_files(wt): + raw = read(wt, f) + if not re.search(r"\bloop_(first|last|first_last)\b", raw): + continue + m = de.mask(raw, f) + edits = [] + # for-loop target lists that unpack a helper directly + for fm in re.finditer(r"\bfor\s+(.+?)\s+in\s+(enumerate\(\s*)?(loop_first_last|loop_first|loop_last)\s*\(", m): + tgt_a, tgt_b = fm.start(1), fm.end(1) + tgt = raw[tgt_a:tgt_b] + fn = fm.group(3) + if fm.group(2): # for i, (a, b, c) in enumerate(helper(...)) + parts = _split_top(tgt) + inner = parts[1] + assert inner.startswith("(") and inner.endswith(")"), (f, tgt) + ip = _split_top(inner[1:-1]) + ip = [ip[-1]] + ip[:-1] + new_tgt = f"{parts[0]}, ({', '.join(ip)})" + else: + parts = _split_top(tgt) + parts = [parts[-1]] + parts[:-1] + new_tgt = ", ".join(parts) + edits.append((tgt_a, tgt_b, new_tgt)) + n_for += 1 + for old, new in _LOOP_RENAME.items(): + for mm in re.finditer(rf"(? str: + r = subprocess.run(["docker", *a], capture_output=True, text=True, timeout=timeout) + if check and r.returncode != 0: + raise RuntimeError(f"docker {a[:3]}: {(r.stdout + r.stderr)[-1500:]}") + return r.stdout + r.stderr + + +class TsBox: + """A node:20 container holding a copy of the checkout plus node_modules.""" + + def __init__(self, wt: Path, repo: str): + self.wt, self.repo = wt, repo + self.name = "deep-ts-" + re.sub(r"[^a-z0-9]+", "-", wt.parent.name.lower())[-50:] + _docker("rm", "-f", self.name, check=False) + _docker("run", "-d", "--name", self.name, "-v", f"{wt}:/src:ro", + "-v", f"{js_eval.NPM_CACHE}:/root/.npm", "-v", f"{js_eval.PNPM_STORE}:/pnpm-store", + "-v", f"{js_eval.BUN_CACHE}:/root/.bun/install/cache", + js_eval.IMAGE, "sleep", "infinity") + self.sync() + out = _docker("exec", "-w", "/w", self.name, "bash", "-c", + f"({js_eval.INSTALL_CMD[repo]}) >/tmp/install.log 2>&1 || {{ tail -40 /tmp/install.log; exit 3; }}") + print(" installed deps", out[-200:], flush=True) + + def sync(self) -> None: + _docker("exec", self.name, "bash", "-c", + "mkdir -p /w && cd /w && find . -path ./node_modules -prune -o -path '*/node_modules' -prune " + "-o -type f -print0 | xargs -0 rm -f; " + "cd /src && tar --exclude=./.git --exclude=node_modules -cf - . | tar -C /w -xf -") + + def tsc(self) -> tuple[bool, list, str]: + self.sync() + r = subprocess.run(["docker", "exec", "-w", "/w", self.name, "bash", "-c", TSC[self.repo] + " 2>&1"], + capture_output=True, text=True, timeout=3600) + out = r.stdout + r.stderr + errs = [(m.group(1), int(m.group(2)), int(m.group(3)), m.group(4), m.group(5)) for m in TS_ERR.finditer(out)] + return r.returncode == 0, errs, out[-3000:] + + def close(self) -> None: + _docker("rm", "-f", self.name, check=False) + + +def tsc_until_clean(box: TsBox, fix_error, rounds: int = 10, baseline: set | None = None) -> None: + """baseline: {(file, code, message)} errors already present at base (zod's + test files carry some); they are ignored.""" + last = None + baseline = baseline or set() + for i in range(rounds): + ok, errs, tail = box.tsc() + errs = [e for e in errs if (e[0], e[3], e[4]) not in baseline] + print(f" tsc round {i}: ok={ok} errors={len(errs)}", flush=True) + if ok or not errs and baseline and "error TS" in tail: + return + if not errs: + raise RuntimeError("tsc failed without parsable errors:\n" + tail) + key = sorted(errs) + if key == last: + raise RuntimeError("no progress:\n" + "\n".join(map(str, errs[:30]))) + last = key + handled = 0 + seen = set() + for e in sorted(errs, key=lambda e: (e[0], -e[1], -e[2])): + if (e[0], e[1]) in seen: + continue + if fix_error(*e): + handled += 1 + seen.add((e[0], e[1])) + if not handled: + raise RuntimeError("unhandled errors:\n" + "\n".join(map(str, errs[:30]))) + raise RuntimeError("did not converge") + + +def ts_files(wt: Path) -> list[str]: + return de.code_files(wt, (".ts", ".tsx", ".mts")) + + +# ------------------------------------------------------------- shared edits + +def make_enclosing_async(raw: str, masked: str, pos: int) -> tuple[int, str] | None: + """Edit (offset, "async ") that makes the function whose body holds pos + async: an arrow `(...) => {`/`x => {`, a `function` or a method `m(...) {`. + None if it is already async.""" + depth = 0 + i = pos - 1 + while i >= 0: + ch = masked[i] + if ch == "}": + depth += 1 + elif ch == "{": + if depth == 0: + before = masked[:i].rstrip() + if before.endswith("=>"): + j = len(before) - 2 + head = masked[:j].rstrip() + if head.endswith(")"): + d, k = 0, len(head) - 1 + while k >= 0: + d += head[k] == ")" + d -= head[k] == "(" + if d == 0: + break + k -= 1 + start = k + else: + m = re.search(r"[\w$]+$", head) + start = m.start() + if re.search(r"\basync\s*$", masked[:start]): + return None + return (start, "async ") + if before.endswith(")"): + d, k = 0, len(before) - 1 + while k >= 0: + d += before[k] == ")" + d -= before[k] == "(" + if d == 0: + break + k -= 1 + m = re.search(r"(\bfunction\s*\*?\s*[\w$]*\s*|[\w$]+\s*)$", masked[:k]) + if m and not re.match(r"(if|for|while|switch|catch)\b", m.group(0).strip()): + if re.search(r"\basync\s*$", masked[:m.start()]): + return None + return (m.start(), "async ") + # a block ({ of if/for/object literal...): keep walking out + else: + depth -= 1 + i -= 1 + return None + + +def line_col_offset(raw: str, line: int, col: int) -> int: + return bd.line_offset(raw, line, col) + + +# build_deep.make_gold copies a fixed set of recipe keys into the spec; TS +# recipes also carry "typecheck_cmd" (js_eval runs it after the suite and +# requires it to pass). Copy it into the spec here, without touching +# build_deep.py: wrap make_gold for recipes that set it. +_orig_make_gold = bd.make_gold + + +def _make_gold_with_extras(tid: str) -> dict: + spec = _orig_make_gold(tid) + r = bd.RECIPES[tid] + extra = {k: r[k] for k in ("typecheck_cmd",) if k in r} + if extra: + spec.update(extra) + import json + (bd.task_dir(tid) / "spec.json").write_text(json.dumps(spec, indent=1)) + return spec + + +if bd.make_gold is _orig_make_gold and getattr(bd.make_gold, "__name__", "") == "make_gold": + bd.make_gold = _make_gold_with_extras + + +HONO_TC = "npx tsc -p tsconfig.spec.json" + +# ------------------------------------------------------------------ T1 +# hono: GetConnInfo (c) => ConnInfo -> (c) => Promise + +GCI_INSTR = ( + "Some runtimes can only look up the client's connection info asynchronously, so hono's " + "connection-info helper has to become async. Change the `GetConnInfo` type in " + "`src/helper/conninfo/types.ts` from `(c: Context) => ConnInfo` to `(c: Context) => Promise`, and " + "make every adapter's `getConnInfo` (aws-lambda, bun, cloudflare-pages, cloudflare-workers, deno, " + "lambda-edge, netlify, vercel) an `async` function returning the same `ConnInfo` as before. Then update " + "every caller to await the result: the `ipRestriction` middleware (which must keep accepting a plain " + "`(c) => string` getter too), every test that calls a `getConnInfo` or defines its own `GetConnInfo`, " + "and every other use. Where a test expected `getConnInfo(c)` to throw, it must now expect the returned " + "promise to reject with the same error. Do not keep a synchronous variant. The connection info returned " + "and the middleware's behavior must not change, and the project must still type-check " + "(`tsc -p tsconfig.spec.json`)." +) + + +@recipe(instance_id="deep__hono__getConnInfo_async", + repo="honojs/hono", lang="ts", repo_dir=HONO, base_commit=HONO_BASE, + change="change return type (sync ConnInfo -> Promise; async cascade into callers)", + instruction=GCI_INSTR, typecheck_cmd=HONO_TC, + decl_files=["src/helper/conninfo/types.ts"], + shapes=[ + {"id": "gci/sync-impl", "regex": r"\bgetConnInfo\s*:\s*GetConnInfo\s*=\s*\("}, + {"id": "gci/sync-type", "regex": r"\bGetConnInfo\s*=\s*\([^)]*\)\s*=>\s*ConnInfo\b"}, + {"id": "gci/unawaited-call", "regex": r"(?\s*\(\{"}, + ], + gold_tool="build_deep.py recipe (deep_recipes_ts): async on each GetConnInfo implementation by pattern, " + "await at every call, enclosing callbacks made async from tsc's TS1308 errors, " + "toThrowError -> rejects.toThrowError; iterated to a clean `tsc -p tsconfig.spec.json`", + notes="The shapes are the sync forms gold removes; an unawaited call left in a test also fails the test " + "(a Promise has no .remote). typecheck_cmd is hono's own pre-test type check.") +def make_gci(wt: Path): + box = TsBox(wt, "honojs/hono") + try: + f = "src/helper/conninfo/types.ts" + write(wt, f, read(wt, f).replace("export type GetConnInfo = (c: Context) => ConnInfo", + "export type GetConnInfo = (c: Context) => Promise")) + for f in ts_files(wt): + raw = read(wt, f) + if "getConnInfo" not in raw and "getIP(" not in raw: + continue + new = re.sub(r"(\bgetConnInfo\s*:\s*GetConnInfo\s*=\s*)\(", r"\1async (", raw) + # expect(() => getConnInfo(c)).toThrowError(X) -> await expect(getConnInfo(c)).rejects.toThrowError(X) + new = re.sub(r"expect\(\(\)\s*=>\s*getConnInfo\((\w+)\)\)\.toThrow(Error)?\(", + r"await expect(getConnInfo(\1)).rejects.toThrow\2(", new) + new = re.sub(r"(?" in msg: + # an inline sync getter `(c) => ({ remote })` handed to ipRestriction + m = de.mask(raw, f) + k = m.rfind("=>", 0, pos + 1) + head = m[:k].rstrip() + if not head.endswith(")"): + return False + start = head.rfind("(") + write(wt, f, raw[:start] + "async " + raw[start:]) + return True + return False + + tsc_until_clean(box, fix) + finally: + box.close() + + +# ------------------------------------------------------------------ T2 +# hono: new HTTPException(status, options?) -> new HTTPException({ status, ...options }) + +HE_INSTR = ( + "`new HTTPException(401, { res })` splits one error description across a positional status and an " + "options bag. Change the constructor of `HTTPException` (src/http-exception.ts) to take a single, " + "required options object that carries the status: `constructor(options: HTTPExceptionOptions & { status: " + "ContentfulStatusCode })`, used as `new HTTPException({ status: 401, res })`. The status is now required " + "(there is no implicit 500 default any more); `res`, `message` and `cause` keep their meaning. Update " + "every `new HTTPException(...)` in the repository -- middleware, helpers, the validator, request " + "handling and all tests -- so each passes the same status and options it passes today. Do not keep the " + "positional form or an overload for it. Behavior must not change, the tests must pass and the project " + "must still type-check (`tsc -p tsconfig.spec.json`)." +) + + +@recipe(instance_id="deep__hono__HTTPException_options_object", + repo="honojs/hono", lang="ts", repo_dir=HONO, base_commit=HONO_BASE, + change="constructor signature change (positional status + options -> one required options object)", + instruction=HE_INSTR, typecheck_cmd=HONO_TC, + decl_files=["src/http-exception.ts"], + shapes=[ + {"id": "he/positional-call", "regex": r"\bHTTPException\s*\(\s*(?!\{)"}, + {"id": "he/positional-ctor", "regex": r"\bconstructor\s*\(\s*status\b"}, + ], + gold_tool="build_deep.py recipe (deep_recipes_ts): every `HTTPException(` call found in comment/string-" + "masked source, its status folded into the options object literal (or spread when the options " + "are not a literal); verified with `tsc -p tsconfig.spec.json`", + notes="The positional-call shape is any HTTPException( whose first argument is not an object literal.") +def make_he(wt: Path): + box = TsBox(wt, "honojs/hono") + try: + f = "src/http-exception.ts" + raw = read(wt, f) + old = (" constructor(status: ContentfulStatusCode = 500, options?: HTTPExceptionOptions) {\n" + " super(options?.message, { cause: options?.cause })\n" + " this.res = options?.res\n" + " this.status = status\n") + new = (" constructor(options: HTTPExceptionOptions & { status: ContentfulStatusCode }) {\n" + " super(options.message, { cause: options.cause })\n" + " this.res = options.res\n" + " this.status = options.status\n") + assert old in raw + raw = raw.replace(old, new) + raw = raw.replace(" * @param status - HTTP status code for the exception. Defaults to 500.\n" + " * @param options - Additional options for the exception.\n", + " * @param options - The status code and additional options for the exception.\n") + write(wt, f, raw) + n = 0 + for f in ts_files(wt): + raw = read(wt, f) + if "HTTPException(" not in raw: + continue + m = de.mask(raw, f) + edits = [] + for c in de.find_calls(raw, m, "HTTPException"): + if c.arity == 0 or m[c.args[0][0]] == "{": + continue + status = raw[c.args[0][0]:c.args[0][1]] + if c.arity == 1: + rep = "{ status: %s }" % status + else: + a, b = c.args[1] + opt = raw[a:b] + if opt.startswith("{"): + inner = opt[1:] + if inner.lstrip().startswith("}"): + rep = "{ status: %s }" % status + elif inner.startswith("\n"): + ind = re.match(r"\n([ \t]*)", inner).group(1) + rep = "{\n" + ind + "status: " + status + "," + inner + else: + rep = "{ status: " + status + "," + (inner if inner.startswith(" ") else " " + inner) + else: + rep = "{ status: %s, ...%s }" % (status, opt) + edits.append((c.args[0][0], c.args[-1][1], rep)) + if edits: + write(wt, f, de.apply_edits(raw, edits)) + n += len(edits) + print(f" rewrote {n} calls") + tsc_until_clean(box, lambda *e: False) + finally: + box.close() + + +# ------------------------------------------------------------------ T3 +# zod v4: codec(in_, out, { decode, encode }) -> codec({ input, output, decode, encode }) + +CODEC_INSTR = ( + "In zod v4 a codec is declared as `z.codec(inputSchema, outputSchema, { decode, encode })`, the only " + "schema factory that splits its definition between positional schemas and an options object. Change " + "`codec` to take one required object: `codec({ input, output, decode, encode })`, where `input` and " + "`output` are the two schemas that used to be the first and second arguments and `decode`/`encode` keep " + "their signatures and meaning. Make this change to both `codec` functions -- zod classic " + "(packages/zod/src/v4/classic/schemas.ts) and zod mini (packages/zod/src/v4/mini/schemas.ts) -- with " + "types that still infer the codec's input and output types from the two schemas. Then update every " + "`codec(...)` call in the repository's code (library code, the bench package and all tests, including " + "calls whose third argument is not an object literal) to the new form, passing the same schemas and " + "functions. Do not keep the three-argument form or an overload for it, and leave unrelated APIs " + "(`invertCodec`, `ZodCodec`, `$ZodCodec`, `pipe`, `transform`) alone. Behavior must not change and the " + "tests must pass." +) + + +@recipe(instance_id="deep__zod__codec_options_object", + repo="colinhacks/zod", lang="ts", repo_dir=ZOD, base_commit=ZOD_BASE, + change="signature change (3 positional parameters -> one required options object), classic + mini", + instruction=CODEC_INSTR, + decl_files=["packages/zod/src/v4/classic/schemas.ts", "packages/zod/src/v4/mini/schemas.ts"], + shapes=[{"id": "codec/3", "name": "codec", "arity": 3}], + gold_tool="build_deep.py recipe (deep_recipes_ts): declarations rewritten by hand-written replacement, " + "every `codec(` call with three top-level arguments folded into one object (spread when the " + "third argument is not a literal); verified with the repo's tsc (packages/zod/tsconfig.json) " + "showing no errors beyond the 15 already present at base", + notes="zod's own tsc config has 15 type errors at base, so no typecheck_cmd; the arity shape catches " + "every unconverted call and any kept 3-parameter declaration.") +def make_codec(wt: Path): + box = TsBox(wt, "colinhacks/zod") + try: + _, base_errs, _ = box.tsc() + baseline = {(e[0], e[3], e[4]) for e in base_errs} + print(f" base tsc errors: {len(base_errs)}") + for f, ret, cls in (("packages/zod/src/v4/classic/schemas.ts", "ZodCodec", "ZodCodec"), + ("packages/zod/src/v4/mini/schemas.ts", "ZodMiniCodec", "ZodMiniCodec")): + raw = read(wt, f) + sa = "SomeType" if "mini" in f else "core.SomeType" + old = (f"export function codec(\n" + " in_: A,\n out: B,\n params: {\n") + new = (f"export function codec(params: {{\n" + " input: A;\n output: B;\n") + assert old in raw, f + raw = raw.replace(old, new) + old2 = (" encode: (value: core.input, payload: core.ParsePayload>) => " + "core.util.MaybeAsync>;\n }\n): " + ret + " {\n") + new2 = (" encode: (value: core.input, payload: core.ParsePayload>) => " + "core.util.MaybeAsync>;\n}): " + ret + " {\n") + assert old2 in raw, f + raw = raw.replace(old2, new2) + raw = raw.replace(" decode: (value: core.output, payload: core.ParsePayload>) => " + "core.util.MaybeAsync>;\n encode:", + " decode: (value: core.output, payload: core.ParsePayload>) => " + "core.util.MaybeAsync>;\n encode:") + raw = raw.replace(" in: in_ as any as core.$ZodType,\n out: out as any as core.$ZodType,\n" + " transform: params.decode as any,", + " in: params.input as any as core.$ZodType,\n out: params.output as any as core.$ZodType,\n" + " transform: params.decode as any,") + write(wt, f, raw) + n = 0 + for f in ts_files(wt): + raw = read(wt, f) + if "codec" not in raw: + continue + m = de.mask(raw, f) + edits = [] + for c in de.find_calls(raw, m, "codec"): + if c.arity != 3 or de.prev_token(m, c.name_start) == "function": + continue + x = raw[c.args[0][0]:c.args[0][1]] + y = raw[c.args[1][0]:c.args[1][1]] + a, b = c.args[2] + p = raw[a:b] + if p.startswith("{"): + inner = p[1:] + if inner.startswith("\n"): + ind = re.match(r"\n([ \t]*)", inner).group(1) + rep = "{\n" + ind + "input: " + x + ",\n" + ind + "output: " + y + "," + inner + else: + rep = "{ input: " + x + ", output: " + y + "," + (inner if inner.startswith(" ") else " " + inner) + else: + rep = "{ input: %s, output: %s, ...%s }" % (x, y, p) + edits.append((c.args[0][0], b, rep)) + if edits: + write(wt, f, de.apply_edits(raw, edits)) + n += len(edits) + print(f" rewrote {n} calls") + tsc_until_clean(box, lambda *e: False, baseline=baseline) + finally: + box.close() + + +# ------------------------------------------------------------------ T4 +# h3: move src/event.ts (H3Event, HTTPEvent, kEventRes...) -> src/core/event.ts + +import posixpath as _pp + +H3_TC = "npx tsc --noEmit -p tsconfig.json" + +MOVE_INSTR = ( + "Start an `src/core/` directory for h3's request primitives: move the module `src/event.ts` -- which " + "defines `H3Event`, `HTTPEvent`, `kEventRes`, `kEventResHeaders` and `kEventResErrHeaders` -- to " + "`src/core/event.ts`, and delete `src/event.ts` (no re-export shim at the old path). Fix the moved " + "module's own relative imports, and update every import or re-export of the old module across the " + "repository -- `src/index.ts`, the router/handler/response modules, the `src/types/` and `src/utils/` " + "modules (including `src/utils/internal/`) and the tests -- to the correct relative path of the new " + "location. Note that `src/utils/event.ts` is a different module (`mockEvent`, `getEventContext`, ...): it " + "stays where it is, and imports of it must not change. The public API exported from `src/index.ts` must " + "not change, the tests must pass and the project must still type-check (`tsc --noEmit -p tsconfig.json`)." +) + + +def _spec_targets(f: str, spec: str) -> str | None: + if not spec.startswith("."): + return None + return _pp.normpath(_pp.join(_pp.dirname(f), spec)) + + +def _rel(f: str, target: str) -> str: + r = _pp.relpath(target, _pp.dirname(f)) + return r if r.startswith(".") else "./" + r + + +@recipe(instance_id="deep__h3__H3Event_module_move", + repo="h3js/h3", lang="ts", repo_dir=H3, base_commit=H3_BASE, + change="move a module (src/event.ts -> src/core/event.ts) and repoint every import", + instruction=MOVE_INSTR, typecheck_cmd=H3_TC, + decl_files=["src/core/event.ts"], + shapes=[ + # any relative specifier ending in event.ts: imports of the look-alike src/utils/event.ts + # are counted too and cancel against gold + {"id": "move/old-specifier", "regex": r"[\"'](?:\.{1,2}/)+(?:src/)?event\.ts[\"']", "raw": True}, + {"id": "move/old-class-file", "regex": r"\bclass\s+H3Event\b"}, + ], + gold_tool="build_deep.py recipe (deep_recipes_ts): file moved, every relative import/export specifier " + "that resolves to src/event.ts recomputed for the new path (posix relpath), the moved file's own " + "imports re-based; verified with `tsc --noEmit -p tsconfig.json`", + notes="old-class-file counts `class H3Event` per file, so an H3Event class left at src/event.ts fails; " + "old-specifier is per file, so look-alike imports of src/utils/event.ts cancel.") +def make_move(wt: Path): + box = TsBox(wt, "h3js/h3") + try: + old, new = "src/event.ts", "src/core/event.ts" + (wt / "src/core").mkdir(exist_ok=True) + raw = read(wt, old) + spec_re = re.compile(r"""((?:from|import)\s*\(?\s*["'])([^"']+)(["'])""") + + def rebase(m): + t = _spec_targets(old, m.group(2)) + if t is None: + return m.group(0) + return m.group(1) + _rel(new, t) + m.group(3) + write(wt, new, spec_re.sub(rebase, raw)) + (wt / old).unlink() + n = 0 + for f in ts_files(wt): + if f == new or not (wt / f).exists(): + continue + raw = read(wt, f) + if "event.ts" not in raw: + continue + + def repoint(m, f=f): + if _spec_targets(f, m.group(2)) == old: + return m.group(1) + _rel(f, new) + m.group(3) + return m.group(0) + out = spec_re.sub(repoint, raw) + if out != raw: + write(wt, f, out) + n += 1 + print(f" repointed imports in {n} files") + tsc_until_clean(box, lambda *e: False) + # partial: forget two TYPE-ONLY imports (erased at runtime, so the suite alone passes; + # the shape and the type check must catch them) + return {"partial_drop": [("src/utils/cors.ts", None), ("src/utils/internal/event-stream.ts", None)]} + finally: + box.close() diff --git a/harness/scoring/bench_monitor.py b/harness/scoring/bench_monitor.py index 0642f842..33dd10b6 100644 --- a/harness/scoring/bench_monitor.py +++ b/harness/scoring/bench_monitor.py @@ -4,16 +4,24 @@ exits 1 (with the reason) on the first bad number: - LOSS: native resolved a task that prism did not - ERROR: any cell recorded an error / agent_error - - RATIO: after >= MIN_PAIRS pairs, prism/native summed cost, tokens, API calls - or turns above RATIO_MAX + - RATIO: after >= MIN_PAIRS pairs, prism/native summed cost above RATIO_MAX + (tokens, API calls and turns are reported, not stop conditions: a ~15% + token overhead from prism's fixed per-request prefix is expected) - PAIR: one pair where prism cost > PAIR_MAX x native (and prism >= $0.30) """ import glob, json, os, sys OUT = sys.argv[1] -MIN_PAIRS, RATIO_MAX, PAIR_MAX = 6, 1.15, 2.5 +MIN_PAIRS, RATIO_MAX, PAIR_MAX = 10, 1.25, 2.5 NATIVE, PRISM = "native", "prism_init" +# Losses already reviewed (one task id per line, '#' comments): counted in the +# totals, no longer a stop reason. +ack_file = os.path.join(OUT, "ACKNOWLEDGED") +ack = set() +if os.path.exists(ack_file): + ack = {l.split("#")[0].strip() for l in open(ack_file)} - {""} + cells = {} for f in glob.glob(os.path.join(OUT, "*.json")): d = json.load(open(f)) @@ -33,7 +41,7 @@ def tok(c): continue n, p = arms[NATIVE], arms[PRISM] rows.append((task, n, p)) - if n.get("resolved") and not p.get("resolved"): + if n.get("resolved") and not p.get("resolved") and task not in ack: bad.append(f"LOSS {task}: native resolved, prism did not") nc, pc = n.get("cost_usd") or 0, p.get("cost_usd") or 0 if nc and pc >= 0.30 and pc > PAIR_MAX * nc: @@ -54,7 +62,7 @@ def total(arm_idx, fn): a, b = total(1, fn), total(2, fn) ratio = b / a if a else 0 print(f" {name:9} native {a:12,.2f} prism {b:12,.2f} prism/native {ratio:.3f}") - if len(rows) >= MIN_PAIRS and ratio > RATIO_MAX: + if name == "cost" and len(rows) >= MIN_PAIRS and ratio > RATIO_MAX: bad.append(f"RATIO {name}: prism/native {ratio:.3f} > {RATIO_MAX} over {len(rows)} pairs") if bad: print("\nSTOP:") diff --git a/harness/scoring/bench_pairs.py b/harness/scoring/bench_pairs.py index 92a04471..74e34bd8 100644 --- a/harness/scoring/bench_pairs.py +++ b/harness/scoring/bench_pairs.py @@ -1,6 +1,6 @@ """Print one line per finished native/prism pair as the run produces them. -usage: bench_pairs.py +usage: bench_pairs.py [--skip-existing] Polls every few seconds; each newly completed pair prints task | native: res turns calls tokens $ | prism: ... | running totals Exits when /DONE exists or the monitor stop file appears. @@ -9,6 +9,7 @@ OUT = sys.argv[1] seen = set() +SKIP_EXISTING = "--skip-existing" in sys.argv # resumed run: totals still count them tot = {"n": 0, "rn": 0, "rp": 0, "cn": 0.0, "cp": 0.0} @@ -19,6 +20,7 @@ def fmt(c): f"{c.get('api_calls') or 0:>3} calls {tok / 1000:>6.0f}k tok ${c.get('cost_usd') or 0:.2f}{err}") +first_pass = True while True: cells = {} for f in glob.glob(os.path.join(OUT, "*.json")): @@ -39,8 +41,11 @@ def fmt(c): tot["cn"] += n.get("cost_usd") or 0 tot["cp"] += p.get("cost_usd") or 0 ratio = tot["cp"] / tot["cn"] if tot["cn"] else 0 + if SKIP_EXISTING and first_pass: + continue print(f"#{tot['n']} {task} | native {fmt(n)} | prism {fmt(p)} | " f"so far resolved native {tot['rn']} prism {tot['rp']}, cost prism/native {ratio:.2f}", flush=True) + first_pass = False if os.path.exists(os.path.join(OUT, "DONE")): stop = os.path.join(OUT, "STOPPED") if os.path.exists(stop): diff --git a/harness/scoring/js_eval.py b/harness/scoring/js_eval.py index 14d23fa8..521aeeca 100644 --- a/harness/scoring/js_eval.py +++ b/harness/scoring/js_eval.py @@ -116,7 +116,7 @@ class PatchError(RuntimeError): def _run_tests(repo_dir: Path, repo: str, base: str, patches: list, image: str = IMAGE, - strict: bool = False) -> dict: + strict: bool = False, typecheck_cmd: str | None = None) -> dict: """Worktree at base + patches; install + the repo's suite in node docker. strict=True (validation) raises PatchError when a patch does not apply; scoring keeps the lenient behaviour (an unappliable agent diff just runs @@ -138,7 +138,7 @@ def _run_tests(repo_dir: Path, repo: str, base: str, patches: list, image: str = "bash", "-c", cmd], capture_output=True, text=True, timeout=1800) return _parse_mocha_json(out.stdout) - return _run_vitest(wt, repo, image) + return _run_vitest(wt, repo, image, typecheck_cmd) finally: subprocess.run(["git", "-C", str(repo_dir), "worktree", "remove", "--force", str(wt)], capture_output=True) @@ -148,12 +148,22 @@ def _run_tests(repo_dir: Path, repo: str, base: str, patches: list, image: str = LAST_LOG = {"text": ""} # tail of the last vitest container run, for diagnosis -def _run_vitest(wt: Path, repo: str, image: str) -> dict: +TC_MARK = "__JS_EVAL_TYPECHECK__" + + +def _run_vitest(wt: Path, repo: str, image: str, typecheck_cmd: str | None = None) -> dict: + """typecheck_cmd (opt-in, a task's "typecheck_cmd", e.g. hono's own + `tsc -p tsconfig.spec.json`) runs after the suite in the same container; + its verdict is reported as the synthetic test "__typecheck__". Without it + the container command is exactly the old one.""" cmd = ("set -o pipefail; mkdir -p /w && tar -C /src --exclude=./.git -cf - . | tar -C /w -xf - && cd /w && " f"({INSTALL_CMD[repo]}) >/tmp/install.log 2>&1 || " "{ echo INSTALL_FAILED; tail -40 /tmp/install.log; exit 3; }; " f"CI=1 {TEST_CMD[repo]} >/tmp/test.log 2>&1; " f"echo {MARK}; cat /tmp/vitest.json 2>/dev/null; echo; echo {MARK}; tail -40 /tmp/test.log") + if typecheck_cmd: + cmd += (f"; ({typecheck_cmd}) >/tmp/tc.log 2>&1 && echo {TC_MARK}PASSED || " + f"{{ echo {TC_MARK}FAILED; tail -40 /tmp/tc.log; }}") out = subprocess.run(["docker", "run", "--rm", "-v", f"{wt}:/src:ro", "-v", f"{NPM_CACHE}:/root/.npm", "-v", f"{PNPM_STORE}:/pnpm-store", @@ -165,7 +175,11 @@ def _run_vitest(wt: Path, repo: str, image: str) -> dict: parts = out.stdout.split(MARK) if len(parts) < 3: return {} - return _parse_vitest_json(parts[1]) + res = _parse_vitest_json(parts[1]) + if typecheck_cmd and res: + tc = re.search(TC_MARK + r"(PASSED|FAILED)", out.stdout) + res["__typecheck__"] = tc.group(1) if tc else "FAILED" + return res def _parse_vitest_json(text: str) -> dict: @@ -254,9 +268,13 @@ def validate(repo_dir: Path, repo: str, task: dict, runs: int = 1) -> dict: def score(repo_dir: Path, repo: str, task: dict, agent_patch: str) -> dict: - res = _run_tests(repo_dir, repo, task["base_commit"], [task["test_patch"], agent_patch]) + tc = task.get("typecheck_cmd") + res = _run_tests(repo_dir, repo, task["base_commit"], [task["test_patch"], agent_patch], + typecheck_cmd=tc) f2p_ok = all(res.get(n) == "PASSED" for n in task["fail_to_pass"]) p2p_ok = all(res.get(n) == "PASSED" for n in task.get("pass_to_pass", [])) + if tc: # the task's own type check is required on top of pass_to_pass + p2p_ok = p2p_ok and res.get("__typecheck__") == "PASSED" return {"resolved": bool(f2p_ok and p2p_ok), "f2p_ok": f2p_ok, "p2p_ok": p2p_ok, "n_run": len(res)} diff --git a/harness/scoring/wide_eval.py b/harness/scoring/wide_eval.py index 74d49091..7fae3817 100644 --- a/harness/scoring/wide_eval.py +++ b/harness/scoring/wide_eval.py @@ -85,13 +85,15 @@ def _strip_comments(path: str, text: str) -> str: return _C_COMMENTS.sub("", text) -def _strip_comments_and_strings(path: str, text: str) -> str: +def _strip_comments_and_strings(path: str, text: str, fill: str = " ") -> str: """Code with comments and string-literal text blanked. A name inside a string (a test title "Should return empty remote", an assertion message "all Route() calls ...") is prose, not a reference: agents that update it were scored as over-renaming (seeded32, 2026-10-05). Code inside f-string / template-literal braces is kept: f"{x.render()}" and `${x.push()}` are - real call sites. Python docstrings are strings, so they go too.""" + real call sites. Python docstrings are strings, so they go too. + fill stands in for each string literal (" " by default; the shapes + oracle passes "0" so a string argument still counts as an argument).""" ext = Path(path).suffix py = ext == ".py" out, i, n = [], 0, len(text) @@ -137,7 +139,7 @@ def keep_braced(j: int, close_at: str) -> int: fstr = "f" in prefix.lower() and (k < 0 or not (out[k].isalnum() or out[k] == "_")) q = text[i:i + 3] if text[i:i + 3] in ("\"\"\"", "\'\'\'") else c j = i + len(q) - out.append(" ") + out.append(fill) while j < n and not text.startswith(q, j): if text[j] == "\\": j += 2 @@ -161,11 +163,11 @@ def keep_braced(j: int, close_at: str) -> int: while j < n and text[j] != "'" and text[j] != "\n": j += 2 if text[j] == "\\" else 1 i = j + 1 - out.append(" ") + out.append(fill) continue q = '"""' if c == '"' and text.startswith('"""', i) and ext in (".java", ".kt") else c j = i + len(q) - out.append(" ") + out.append(fill) while j < n and not text.startswith(q, j): if text[j] == "\\" and not (c == "`" and ext == ".go"): j += 2 @@ -277,6 +279,99 @@ def file_site_check(repo: Path, task: dict, patch: str) -> dict: "missed_files": missed, "stale": stale} +_OPEN, _CLOSE = "([{", ")]}" + + +def call_arities(text: str, name: str) -> list[int]: + """Top-level argument count of every `name(...)` in comment/string-stripped + code: calls and declarations alike (`def f(a, b)`, `void f(A a, B b)`, + `F(a int) error` all count). An explicit type-argument list right after + the name (`name(`) is skipped. A trailing comma adds no argument.""" + out = [] + for m in re.finditer(rf"(?()]*(?:<[^<>()]*>[^<>()]*)*>)?\s*\(", text): + i, depth, commas, seg = m.end(), 1, 0, "" + nonempty = False + while i < len(text) and depth: + ch = text[i] + if ch in _OPEN: + depth += 1 + elif ch in _CLOSE: + depth -= 1 + if not depth: + break + if depth == 1 and ch == ",": + commas += 1 + seg = "" + elif not ch.isspace(): + seg += ch + nonempty = True + i += 1 + if not nonempty: + out.append(0) + else: + out.append(commas + (1 if seg else 0)) + return out + + +def shape_counts(root: Path, shapes: list[dict]) -> dict[str, dict[str, int]]: + """{shape id: {relative code file: count}} for the files where it occurs. + A shape is {"id", "name", "arity"} (calls/declarations of `name` with + that many top-level arguments), {"id", "name"} (identifier tokens), or + {"id", "regex"} (matches; over raw text when "raw" is true, e.g. Go/TS + import paths, which are string literals).""" + out = {s["id"]: {} for s in shapes} + files = _sh("git", "-C", str(root), "ls-files", "-co", "--exclude-standard").splitlines() + for rel in files: + if Path(rel).suffix not in CODE_EXT or SKIP_DIR.search(rel): + continue + try: + raw = (root / rel).read_text(errors="ignore") + except OSError: + continue + code = None + for s in shapes: + if s.get("raw"): + n = len(re.findall(s["regex"], raw, re.M)) + else: + if "name" in s and s["name"] not in raw: + continue + if code is None: + code = _strip_comments_and_strings(rel, raw, fill="0") + if "regex" in s: + n = len(re.findall(s["regex"], code, re.M)) + elif "arity" in s: + n = sum(1 for a in call_arities(code, s["name"]) if a == s["arity"]) + else: + n = len(re.findall(rf"(? dict: + """site_mode="shapes" (seeded deep changes: add a parameter, change a + return type, move a type): every shape names an OLD form that the change + removes -- a call or declaration of the method with its old argument + count, the type's old import path, the old name. In no file may the + patched tree have more occurrences of a shape than the gold tree: one + more is a call site, override or import the patch did not update. + Look-alikes (same name and arity on an unrelated type) are in the gold + counts too, so they cancel. Per-file counts, not lines, so an equivalent + edit that moves code still scores.""" + wt = _checkout(repo, task["base_commit"], patch) + try: + got = shape_counts(wt, task["shapes"]) + finally: + shutil.rmtree(wt, ignore_errors=True) + left = [] + for sid, gold in task["gold_shape_counts"].items(): + for f, n in sorted(got.get(sid, {}).items()): + if n > gold.get(f, 0): + left.append({"shape": sid, "file": f, "want": gold.get(f, 0), "got": n}) + return {"sites_ok": not left, "gold_sites": task.get("gold_sites"), + "missed_sites": sum(e["got"] - e["want"] for e in left), "left": left[:30]} + + def _lang_score(task: dict, patch: str) -> dict: """The language's own build+test scorer, pass_to_pass only.""" import run_e2e # the dispatch table and repo lookup live there @@ -303,7 +398,7 @@ def score(task: dict, agent_patch: str) -> dict: if not agent_patch.strip(): return {"resolved": False, "empty_diff": True} try: - check = file_site_check if task.get("site_mode") == "files" else site_check + check = {"files": file_site_check, "shapes": shape_site_check}.get(task.get("site_mode"), site_check) sites = check(repo_dir(task), task, agent_patch) except RuntimeError as e: return {"resolved": False, "error": str(e)[:300]} diff --git a/harness/tasks/e2e/deep__cli__ValueCreator_Create_return_error.json b/harness/tasks/e2e/deep__cli__ValueCreator_Create_return_error.json new file mode 100644 index 00000000..8a9e2781 --- /dev/null +++ b/harness/tasks/e2e/deep__cli__ValueCreator_Create_return_error.json @@ -0,0 +1,1230 @@ +{ + "instance_id": "deep__cli__ValueCreator_Create_return_error", + "repo": "urfave/cli", + "lang": "go", + "base_commit": "58ec406eff149315193d8632c08317f70f6deee1", + "instruction": "`ValueCreator.Create` (flag_impl.go) cannot report a bad default or config: it returns only a `Value`. Change its return type to `(Value, error)`, so the interface method becomes `Create(T, *T, C) (Value, error)`. Change every implementation (boolValue, durationValue, floatValue, genericValue, intValue, uintValue, stringValue, textValue, timestampValue, MapBase, SliceBase and any other) to the new signature; the existing implementations never fail and return a nil error. Update every caller, in source and in tests, to handle the error: where the calling function returns an error, return it (`ArgumentBase.Parse`, `ArgumentsBase.Parse`, `FlagBase.PreParse`, and `MapBase.Create` / `SliceBase.Create`, which call the element creator); in tests, fail the test on a non-nil error (`require.NoError`/`t.Fatal`), or panic inside helper closures that have no `*testing.T`. Do not keep a single-result variant or wrapper. Do not touch unrelated `Create` functions such as `os.Create`. Behavior must not change.", + "shapes": [ + { + "id": "Create/returns-Value", + "regex": "\\bCreate\\s*\\([^()]*\\)\\s*Value\\b" + }, + { + "id": "Create/single-value-use", + "regex": "(?m)^\\s*[\\w.]+\\s*:?=\\s*[\\w.]+\\.Create\\(|\\b\\w+:\\s*[\\w.]+\\.Create\\(" + } + ], + "source": "seeded", + "site_mode": "shapes", + "gold_tool": "build_deep.py go recipe: declarations by pattern (return type Value -> (Value, error), `return x` -> `return x, nil` in their bodies), callers rewritten by explicit per-site edits, go build + go test compile clean (go1.25.14 GOTOOLCHAIN=local); gofmt", + "change": "change return type T -> (T, error) (generic interface method: 12 implementations + callers that must restructure expression uses into error handling)", + "notes": "Call sites are guarded by the compiler (a two-result call in single-value context does not compile) and by the single-value-use regex shape.", + "kind": "wide", + "patch": "diff --git a/args.go b/args.go\nindex 0dad2099..ee8d18b7 100644\n--- a/args.go\n+++ b/args.go\n@@ -133,7 +133,10 @@ func (a *ArgumentBase[T, C, VC]) Parse(s []string) ([]string, error) {\n \n \tvar vc VC\n \tvar t T\n-\tvalue := vc.Create(a.Value, &t, a.Config)\n+\tvalue, err := vc.Create(a.Value, &t, a.Config)\n+\tif err != nil {\n+\t\treturn s, err\n+\t}\n \ta.value = &t\n \n \ttracef(\"attempting arg%[1] parse\", &a.Name)\n@@ -210,7 +213,10 @@ func (a *ArgumentsBase[T, C, VC]) Parse(s []string) ([]string, error) {\n \tcount := 0\n \tvar vc VC\n \tvar t T\n-\tvalue := vc.Create(a.Value, &t, a.Config)\n+\tvalue, err := vc.Create(a.Value, &t, a.Config)\n+\tif err != nil {\n+\t\treturn s, err\n+\t}\n \ta.values = []T{}\n \n \ttracef(\"attempting arg%[1] parse\", &a.Name)\ndiff --git a/flag_bool.go b/flag_bool.go\nindex f0ec22fa..93560ae7 100644\n--- a/flag_bool.go\n+++ b/flag_bool.go\n@@ -37,7 +37,7 @@ func (cmd *Command) Bool(name string) bool {\n // Below functions are to satisfy the ValueCreator interface\n \n // Create creates the bool value\n-func (b boolValue) Create(val bool, p *bool, c BoolConfig) Value {\n+func (b boolValue) Create(val bool, p *bool, c BoolConfig) (Value, error) {\n \t*p = val\n \tif c.Count == nil {\n \t\tc.Count = new(int)\n@@ -45,7 +45,7 @@ func (b boolValue) Create(val bool, p *bool, c BoolConfig) Value {\n \treturn &boolValue{\n \t\tdestination: p,\n \t\tcount: c.Count,\n-\t}\n+\t}, nil\n }\n \n // ToString formats the bool value\ndiff --git a/flag_duration.go b/flag_duration.go\nindex 634789d1..032cf554 100644\n--- a/flag_duration.go\n+++ b/flag_duration.go\n@@ -12,9 +12,9 @@ type durationValue time.Duration\n \n // Below functions are to satisfy the ValueCreator interface\n \n-func (d durationValue) Create(val time.Duration, p *time.Duration, c NoConfig) Value {\n+func (d durationValue) Create(val time.Duration, p *time.Duration, c NoConfig) (Value, error) {\n \t*p = val\n-\treturn (*durationValue)(p)\n+\treturn (*durationValue)(p), nil\n }\n \n func (d durationValue) ToString(val time.Duration) string {\ndiff --git a/flag_float.go b/flag_float.go\nindex 6173e80d..8f05884d 100644\n--- a/flag_float.go\n+++ b/flag_float.go\n@@ -18,10 +18,10 @@ type floatValue[T float32 | float64] struct {\n \n // Below functions are to satisfy the ValueCreator interface\n \n-func (f floatValue[T]) Create(val T, p *T, c NoConfig) Value {\n+func (f floatValue[T]) Create(val T, p *T, c NoConfig) (Value, error) {\n \t*p = val\n \n-\treturn &floatValue[T]{val: p}\n+\treturn &floatValue[T]{val: p}, nil\n }\n \n func (f floatValue[T]) ToString(b T) string {\ndiff --git a/flag_generic.go b/flag_generic.go\nindex 5ee07c7a..7c9dc95d 100644\n--- a/flag_generic.go\n+++ b/flag_generic.go\n@@ -9,11 +9,11 @@ type genericValue struct {\n \n // Below functions are to satisfy the ValueCreator interface\n \n-func (f genericValue) Create(val Value, p *Value, c NoConfig) Value {\n+func (f genericValue) Create(val Value, p *Value, c NoConfig) (Value, error) {\n \t*p = val\n \treturn &genericValue{\n \t\tval: *p,\n-\t}\n+\t}, nil\n }\n \n func (f genericValue) ToString(b Value) string {\ndiff --git a/flag_impl.go b/flag_impl.go\nindex beea6013..44ca9440 100644\n--- a/flag_impl.go\n+++ b/flag_impl.go\n@@ -40,7 +40,7 @@ type multiValueParsingConfigSetter interface {\n //\tT specifies the type\n //\tC specifies the config for the type\n type ValueCreator[T any, C any] interface {\n-\tCreate(T, *T, C) Value\n+\tCreate(T, *T, C) (Value, error)\n \tToString(T) string\n }\n \n@@ -170,11 +170,15 @@ func (f *FlagBase[T, C, V]) setMultiValueParsingConfig(c multiValueParsingConfig\n func (f *FlagBase[T, C, V]) PreParse() error {\n \tnewVal := f.Value\n \n-\tif f.Destination == nil {\n-\t\tf.value = f.creator.Create(newVal, new(T), f.Config)\n-\t} else {\n-\t\tf.value = f.creator.Create(newVal, f.Destination, f.Config)\n+\tdest := f.Destination\n+\tif dest == nil {\n+\t\tdest = new(T)\n \t}\n+\tvalue, err := f.creator.Create(newVal, dest, f.Config)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\tf.value = value\n \n \t// Validate the given default or values set from external sources as well\n \tif f.Validator != nil && f.ValidateDefaults {\ndiff --git a/flag_int.go b/flag_int.go\nindex 8e5af170..d975ca5a 100644\n--- a/flag_int.go\n+++ b/flag_int.go\n@@ -26,13 +26,13 @@ type intValue[T int | int8 | int16 | int32 | int64] struct {\n \n // Below functions are to satisfy the ValueCreator interface\n \n-func (i intValue[T]) Create(val T, p *T, c IntegerConfig) Value {\n+func (i intValue[T]) Create(val T, p *T, c IntegerConfig) (Value, error) {\n \t*p = val\n \n \treturn &intValue[T]{\n \t\tval: p,\n \t\tbase: c.Base,\n-\t}\n+\t}, nil\n }\n \n func (i intValue[T]) ToString(b T) string {\ndiff --git a/flag_int_test.go b/flag_int_test.go\nindex 47b8f690..b6d1f50a 100644\n--- a/flag_int_test.go\n+++ b/flag_int_test.go\n@@ -358,7 +358,9 @@ func TestIntFlagExt(t *testing.T) {\n \n \t\t\tf := &extFlag{f: tt.flag}\n \n-\t\t\ttt.flag.Value = uValue.Create(u, &u, tt.config)\n+\t\t\tvalue, createErr := uValue.Create(u, &u, tt.config)\n+\t\t\trequire.NoError(t, createErr)\n+\t\t\ttt.flag.Value = value\n \n \t\t\tif tt.config.Base != 0 && tt.config.Base != 10 {\n \t\t\t\tt.Skipf(\"skipping %q with base %d, only base 10 is supported\", tt.name, tt.config.Base)\ndiff --git a/flag_map_impl.go b/flag_map_impl.go\nindex dfe8f097..f22e31fb 100644\n--- a/flag_map_impl.go\n+++ b/flag_map_impl.go\n@@ -17,7 +17,7 @@ type MapBase[T any, C any, VC ValueCreator[T, C]] struct {\n \tmultiValueConfig multiValueParsingConfig\n }\n \n-func (i MapBase[T, C, VC]) Create(val map[string]T, p *map[string]T, c C) Value {\n+func (i MapBase[T, C, VC]) Create(val map[string]T, p *map[string]T, c C) (Value, error) {\n \t*p = map[string]T{}\n \tfor k, v := range val {\n \t\t(*p)[k] = v\n@@ -31,11 +31,15 @@ func (i MapBase[T, C, VC]) Create(val map[string]T, p *map[string]T, c C) Value\n \tif sc, ok := any(c).(StringConfig); ok {\n \t\ttrimKeySpace = sc.TrimSpace\n \t}\n+\tvalue, err := vc.Create(t, np, c)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n \treturn &MapBase[T, C, VC]{\n \t\tdict: p,\n-\t\tvalue: vc.Create(t, np, c),\n+\t\tvalue: value,\n \t\ttrimKeySpace: trimKeySpace,\n-\t}\n+\t}, nil\n }\n \n // NewMapBase makes a *MapBase with default values\ndiff --git a/flag_schema_type_test.go b/flag_schema_type_test.go\nindex 6870730f..5766c341 100644\n--- a/flag_schema_type_test.go\n+++ b/flag_schema_type_test.go\n@@ -137,7 +137,11 @@ func TestExtFlag_SchemaType(t *testing.T) {\n \t\t\tmakeFlag: func() *extFlag {\n \t\t\t\tvar bv boolValue\n \t\t\t\tvar p bool\n-\t\t\t\treturn &extFlag{f: &flag.Flag{Value: bv.Create(true, &p, BoolConfig{})}}\n+\t\t\t\tvalue, err := bv.Create(true, &p, BoolConfig{})\n+\t\t\t\tif err != nil {\n+\t\t\t\t\tpanic(err)\n+\t\t\t\t}\n+\t\t\t\treturn &extFlag{f: &flag.Flag{Value: value}}\n \t\t\t},\n \t\t\tschemaType: \"boolean\",\n \t\t},\n@@ -146,7 +150,11 @@ func TestExtFlag_SchemaType(t *testing.T) {\n \t\t\tmakeFlag: func() *extFlag {\n \t\t\t\tvar sv stringValue\n \t\t\t\tvar p string\n-\t\t\t\treturn &extFlag{f: &flag.Flag{Value: sv.Create(\"hi\", &p, StringConfig{})}}\n+\t\t\t\tvalue, err := sv.Create(\"hi\", &p, StringConfig{})\n+\t\t\t\tif err != nil {\n+\t\t\t\t\tpanic(err)\n+\t\t\t\t}\n+\t\t\t\treturn &extFlag{f: &flag.Flag{Value: value}}\n \t\t\t},\n \t\t\tschemaType: \"string\",\n \t\t},\n@@ -155,7 +163,11 @@ func TestExtFlag_SchemaType(t *testing.T) {\n \t\t\tmakeFlag: func() *extFlag {\n \t\t\t\tvar fv floatValue[float64]\n \t\t\t\tvar p float64\n-\t\t\t\treturn &extFlag{f: &flag.Flag{Value: fv.Create(3.14, &p, NoConfig{})}}\n+\t\t\t\tvalue, err := fv.Create(3.14, &p, NoConfig{})\n+\t\t\t\tif err != nil {\n+\t\t\t\t\tpanic(err)\n+\t\t\t\t}\n+\t\t\t\treturn &extFlag{f: &flag.Flag{Value: value}}\n \t\t\t},\n \t\t\tschemaType: \"number\",\n \t\t},\n@@ -164,7 +176,11 @@ func TestExtFlag_SchemaType(t *testing.T) {\n \t\t\tmakeFlag: func() *extFlag {\n \t\t\t\tvar dv durationValue\n \t\t\t\tvar p time.Duration\n-\t\t\t\treturn &extFlag{f: &flag.Flag{Value: dv.Create(5*time.Second, &p, NoConfig{})}}\n+\t\t\t\tvalue, err := dv.Create(5*time.Second, &p, NoConfig{})\n+\t\t\t\tif err != nil {\n+\t\t\t\t\tpanic(err)\n+\t\t\t\t}\n+\t\t\t\treturn &extFlag{f: &flag.Flag{Value: value}}\n \t\t\t},\n \t\t\tschemaType: \"duration\",\n \t\t},\n@@ -173,7 +189,11 @@ func TestExtFlag_SchemaType(t *testing.T) {\n \t\t\tmakeFlag: func() *extFlag {\n \t\t\t\tvar tv timestampValue\n \t\t\t\tvar p time.Time\n-\t\t\t\treturn &extFlag{f: &flag.Flag{Value: tv.Create(time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC), &p, TimestampConfig{})}}\n+\t\t\t\tvalue, err := tv.Create(time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC), &p, TimestampConfig{})\n+\t\t\t\tif err != nil {\n+\t\t\t\t\tpanic(err)\n+\t\t\t\t}\n+\t\t\t\treturn &extFlag{f: &flag.Flag{Value: value}}\n \t\t\t},\n \t\t\tschemaType: \"date-time\",\n \t\t},\ndiff --git a/flag_slice_base.go b/flag_slice_base.go\nindex 1f9561ae..c3d96b37 100644\n--- a/flag_slice_base.go\n+++ b/flag_slice_base.go\n@@ -16,16 +16,20 @@ type SliceBase[T any, C any, VC ValueCreator[T, C]] struct {\n \tdisableSliceSeparator bool\n }\n \n-func (i SliceBase[T, C, VC]) Create(val []T, p *[]T, c C) Value {\n+func (i SliceBase[T, C, VC]) Create(val []T, p *[]T, c C) (Value, error) {\n \t*p = []T{}\n \t*p = append(*p, val...)\n \tvar t T\n \tnp := new(T)\n \tvar vc VC\n+\tvalue, err := vc.Create(t, np, c)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n \treturn &SliceBase[T, C, VC]{\n \t\tslice: p,\n-\t\tvalue: vc.Create(t, np, c),\n-\t}\n+\t\tvalue: value,\n+\t}, nil\n }\n \n // NewSliceBase makes a *SliceBase with default values\ndiff --git a/flag_string.go b/flag_string.go\nindex ca24b379..fd644855 100644\n--- a/flag_string.go\n+++ b/flag_string.go\n@@ -21,12 +21,12 @@ type stringValue struct {\n \n // Below functions are to satisfy the ValueCreator interface\n \n-func (s stringValue) Create(val string, p *string, c StringConfig) Value {\n+func (s stringValue) Create(val string, p *string, c StringConfig) (Value, error) {\n \t*p = val\n \treturn &stringValue{\n \t\tdestination: p,\n \t\ttrimSpace: c.TrimSpace,\n-\t}\n+\t}, nil\n }\n \n func (s stringValue) ToString(val string) string {\ndiff --git a/flag_test.go b/flag_test.go\nindex d48bda4f..b0f283ea 100644\n--- a/flag_test.go\n+++ b/flag_test.go\n@@ -3344,10 +3344,13 @@ func TestExtFlag(t *testing.T) {\n \tvar iv intValue[int64]\n \tvar ipv int64\n \n+\tvalue, err := iv.Create(11, &ipv, IntegerConfig{})\n+\trequire.NoError(t, err)\n+\n \tf := &flag.Flag{\n \t\tName: \"bar\",\n \t\tUsage: \"bar usage\",\n-\t\tValue: iv.Create(11, &ipv, IntegerConfig{}),\n+\t\tValue: value,\n \t\tDefValue: \"10\",\n \t}\n \ndiff --git a/flag_text.go b/flag_text.go\nindex a1cc2c36..86037d1f 100644\n--- a/flag_text.go\n+++ b/flag_text.go\n@@ -24,7 +24,7 @@ type textValue struct {\n \n // Below functions are to satisfy the ValueCreator interface\n \n-func (t textValue) Create(val TextMarshalUnmarshaler, p *TextMarshalUnmarshaler, c StringConfig) Value {\n+func (t textValue) Create(val TextMarshalUnmarshaler, p *TextMarshalUnmarshaler, c StringConfig) (Value, error) {\n \t// Only overwrite the target when a non-nil default value is given, so that\n \t// a Destination pointing at an existing target is preserved (unlike the\n \t// concrete flag types, T here is an interface whose nil default would\n@@ -35,7 +35,7 @@ func (t textValue) Create(val TextMarshalUnmarshaler, p *TextMarshalUnmarshaler,\n \treturn &textValue{\n \t\tdestination: *p,\n \t\ttrimSpace: c.TrimSpace,\n-\t}\n+\t}, nil\n }\n \n func (t textValue) ToString(val TextMarshalUnmarshaler) string {\ndiff --git a/flag_timestamp.go b/flag_timestamp.go\nindex 83723e6f..700a6655 100644\n--- a/flag_timestamp.go\n+++ b/flag_timestamp.go\n@@ -31,13 +31,13 @@ var _ ValueCreator[time.Time, TimestampConfig] = timestampValue{}\n \n // Below functions are to satisfy the ValueCreator interface\n \n-func (t timestampValue) Create(val time.Time, p *time.Time, c TimestampConfig) Value {\n+func (t timestampValue) Create(val time.Time, p *time.Time, c TimestampConfig) (Value, error) {\n \t*p = val\n \treturn ×tampValue{\n \t\ttimestamp: p,\n \t\tlayouts: c.Layouts,\n \t\tlocation: c.Timezone,\n-\t}\n+\t}, nil\n }\n \n func (t timestampValue) ToString(b time.Time) string {\ndiff --git a/flag_uint.go b/flag_uint.go\nindex 98185794..ab502187 100644\n--- a/flag_uint.go\n+++ b/flag_uint.go\n@@ -21,13 +21,13 @@ type uintValue[T uint | uint8 | uint16 | uint32 | uint64] struct {\n \n // Below functions are to satisfy the ValueCreator interface\n \n-func (i uintValue[T]) Create(val T, p *T, c IntegerConfig) Value {\n+func (i uintValue[T]) Create(val T, p *T, c IntegerConfig) (Value, error) {\n \t*p = val\n \n \treturn &uintValue[T]{\n \t\tval: p,\n \t\tbase: c.Base,\n-\t}\n+\t}, nil\n }\n \n func (i uintValue[T]) ToString(b T) string {\ndiff --git a/flag_uint_test.go b/flag_uint_test.go\nindex 99557fd6..de0f5d91 100644\n--- a/flag_uint_test.go\n+++ b/flag_uint_test.go\n@@ -352,7 +352,9 @@ func TestUintFlagExt(t *testing.T) {\n \n \t\t\tf := &extFlag{f: tt.flag}\n \n-\t\t\ttt.flag.Value = uValue.Create(u, &u, tt.config)\n+\t\t\tvalue, createErr := uValue.Create(u, &u, tt.config)\n+\t\t\trequire.NoError(t, createErr)\n+\t\t\ttt.flag.Value = value\n \n \t\t\tcmd := &Command{\n \t\t\t\tName: \"mock\",\n", + "test_patch": "", + "fail_to_pass": [], + "problem_statement": "`ValueCreator.Create` (flag_impl.go) cannot report a bad default or config: it returns only a `Value`. Change its return type to `(Value, error)`, so the interface method becomes `Create(T, *T, C) (Value, error)`. Change every implementation (boolValue, durationValue, floatValue, genericValue, intValue, uintValue, stringValue, textValue, timestampValue, MapBase, SliceBase and any other) to the new signature; the existing implementations never fail and return a nil error. Update every caller, in source and in tests, to handle the error: where the calling function returns an error, return it (`ArgumentBase.Parse`, `ArgumentsBase.Parse`, `FlagBase.PreParse`, and `MapBase.Create` / `SliceBase.Create`, which call the element creator); in tests, fail the test on a non-nil error (`require.NoError`/`t.Fatal`), or panic inside helper closures that have no `*testing.T`. Do not keep a single-result variant or wrapper. Do not touch unrelated `Create` functions such as `os.Create`. Behavior must not change.", + "prompt_source": "wide-mandate", + "gold_files": [ + "args.go", + "flag_bool.go", + "flag_duration.go", + "flag_float.go", + "flag_generic.go", + "flag_impl.go", + "flag_int.go", + "flag_int_test.go", + "flag_map_impl.go", + "flag_schema_type_test.go", + "flag_slice_base.go", + "flag_string.go", + "flag_test.go", + "flag_text.go", + "flag_timestamp.go", + "flag_uint.go", + "flag_uint_test.go" + ], + "base_shape_counts": { + "Create/returns-Value": { + "flag_bool.go": 1, + "flag_duration.go": 1, + "flag_float.go": 1, + "flag_generic.go": 1, + "flag_impl.go": 1, + "flag_int.go": 1, + "flag_map_impl.go": 1, + "flag_slice_base.go": 1, + "flag_string.go": 1, + "flag_text.go": 1, + "flag_timestamp.go": 1, + "flag_uint.go": 1 + }, + "Create/single-value-use": { + "args.go": 2, + "flag_impl.go": 2, + "flag_int_test.go": 1, + "flag_map_impl.go": 1, + "flag_schema_type_test.go": 5, + "flag_slice_base.go": 1, + "flag_test.go": 1, + "flag_uint_test.go": 1 + } + }, + "gold_shape_counts": { + "Create/returns-Value": {}, + "Create/single-value-use": {} + }, + "gold_sites": 26, + "gold_site_files": 17, + "test_functions": [ + "TestArgNotSet", + "TestArgUsage", + "TestArgsConsumedByNamedArguments", + "TestArgsFloatSliceTypes", + "TestArgsFloatTypes", + "TestArgsIntSliceTypes", + "TestArgsIntTypes", + "TestArgsMaxNotSet", + "TestArgsMinGtMax", + "TestArgsUintSliceTypes", + "TestArgsUintTypes", + "TestArgsUsage", + "TestArgumentRequiredUsageInCommandHelp", + "TestArgumentsInvalidType", + "TestArgumentsRootCommand", + "TestArgumentsSubcommand", + "TestBoolFlagApply_SetsAllNames", + "TestBoolFlagApply_SetsCount", + "TestBoolFlagCountFromCommand", + "TestBoolFlagHelpOutput", + "TestBoolFlagTerminator", + "TestBoolFlagValueFromCommand", + "TestBoolInverseFlagDefaultValidation", + "TestBoolInverseFlagValidation", + "TestBoolWithInverseAction", + "TestBoolWithInverseAlias", + "TestBoolWithInverseBasic", + "TestBoolWithInverseDefaultText", + "TestBoolWithInverseDestination", + "TestBoolWithInverseEnvVars", + "TestBoolWithInverseFlagCount", + "TestBoolWithInverseFlagStringNoPanicWithNoTabStringer", + "TestBoolWithInverseFlag_SatisfiesRequiredFlagInterface", + "TestBoolWithInverseFlag_SatisfiesVisibleFlagInterface", + "TestBoolWithInverseNames", + "TestBoolWithInverseRequired", + "TestBoolWithInverseString", + "TestBoolWithInverseWithPrefix", + "TestCategorizedHelp", + "TestChainedRequiredArgs", + "TestCheckRequiredArgumentsSkipsHelpAndCompletionCommands", + "TestCheckRequiredFlags", + "TestCheckRequiredFlagsWithOnUsageError", + "TestCliArgContainsFlag", + "TestCommandAttributeAccessing", + "TestCommandCategories", + "TestCommandFlagParsing", + "TestCommandHelpPrinter", + "TestCommandHelpSuggest", + "TestCommandInvalidName", + "TestCommandMapKeyValueFlagSeparator", + "TestCommandNoHelpFlag", + "TestCommandReadArgsFromStdIn", + "TestCommandSkipFlagParsing", + "TestCommandSliceFlagSeparator", + "TestCommandSliceFlagSeparatorFromEnvVar", + "TestCommandStringDashOption", + "TestCommand_AfterFunc", + "TestCommand_AfterNotCalledOnSubcommandHelp", + "TestCommand_AfterStillCalledOnNormalSubcommand", + "TestCommand_ArgValidator_ErrorShortCircuitsAction", + "TestCommand_ArgValidator_InheritsFromParent", + "TestCommand_ArgValidator_RunsBeforeAction", + "TestCommand_ArgValidator_RunsBeforeBefore", + "TestCommand_ArgValidator_SubcommandOverride", + "TestCommand_Args", + "TestCommand_BareDash", + "TestCommand_BeforeAfterFuncShellCompletion", + "TestCommand_BeforeFunc", + "TestCommand_BeforeFuncPersistentFlag", + "TestCommand_Bool", + "TestCommand_CanAddVFlagOnSubCommands", + "TestCommand_Command", + "TestCommand_CommandNotFound", + "TestCommand_CommandWithDash", + "TestCommand_CommandWithFlagBeforeTerminator", + "TestCommand_CommandWithNoFlagBeforeTerminator", + "TestCommand_DefaultStdin", + "TestCommand_DefaultStdout", + "TestCommand_Deprecated", + "TestCommand_DeprecatedStillRuns", + "TestCommand_Duration", + "TestCommand_EqualsFlagValueValidation", + "TestCommand_ExclusiveFlags", + "TestCommand_ExclusiveFlagsPersistent", + "TestCommand_ExclusiveFlagsWithAfter", + "TestCommand_ExclusiveFlagsWithOnUsageError", + "TestCommand_FlagValuesKeepWhitespace", + "TestCommand_FlagsFromExtPackage", + "TestCommand_Float32Slice", + "TestCommand_Float64", + "TestCommand_Float64Flag", + "TestCommand_Float64Slice", + "TestCommand_FloatSlice", + "TestCommand_HelpFlagTakesPrecedenceOverParseErrors", + "TestCommand_IncorrectUsageOnMutuallyExclusiveFlagsViaRun", + "TestCommand_IncorrectUsageOnRequiredFlagsViaRun", + "TestCommand_IncorrectUsageOnSubcommandWithFailingShowCommandHelp", + "TestCommand_Int", + "TestCommand_Int16Slice", + "TestCommand_Int32Slice", + "TestCommand_Int64Slice", + "TestCommand_Int8Slice", + "TestCommand_IntSlice", + "TestCommand_IsSet", + "TestCommand_IsSet_fromEnv", + "TestCommand_NoDefaultCmdArgMatchingFlag", + "TestCommand_NumFlags", + "TestCommand_OnUsageError_WithSubcommand", + "TestCommand_OnUsageError_WithWrongFlagValue", + "TestCommand_OnUsageError_WithWrongFlagValue_ForSubcommand", + "TestCommand_OnUsageError_hasCommandContext", + "TestCommand_OrderOfOperations", + "TestCommand_ParallelRun", + "TestCommand_ParentCommand_Set", + "TestCommand_ParseSliceFlags", + "TestCommand_ParseSliceFlagsWithMissingValue", + "TestCommand_Path", + "TestCommand_PositionalArgsKeepWhitespace", + "TestCommand_Run", + "TestCommand_RunDefaultCommand", + "TestCommand_RunDefaultCommandWithFlags", + "TestCommand_RunDefaultCommandWithSubCommand", + "TestCommand_RunSubcommandWithDefault", + "TestCommand_Run_BeforeReturnNewContext", + "TestCommand_Run_BeforeReturnNewContextSubcommand", + "TestCommand_Run_BeforeSavesMetadata", + "TestCommand_Run_Categories", + "TestCommand_Run_CommandWithSubcommandHasHelpTopic", + "TestCommand_Run_CustomFlagCanUseVersionAlias", + "TestCommand_Run_CustomShellCompleteAcceptsMalformedFlags", + "TestCommand_Run_DoesNotOverwriteErrorFromBefore", + "TestCommand_Run_FlagActionContext", + "TestCommand_Run_Help", + "TestCommand_Run_SubcommandDoesNotOverwriteErrorFromBefore", + "TestCommand_Run_SubcommandFullPath", + "TestCommand_Run_SubcommandsCanUseErrWriter", + "TestCommand_Run_Version", + "TestCommand_Set", + "TestCommand_SetStdin", + "TestCommand_SetStdin_Subcommand", + "TestCommand_SetStdout", + "TestCommand_Set_InvalidFlagAccessHandler", + "TestCommand_Setup_defaultsReader", + "TestCommand_Setup_defaultsWriter", + "TestCommand_SingleRuneUnicodeFlag", + "TestCommand_SkipFlagParsing", + "TestCommand_StopOnNthArg", + "TestCommand_StopOnNthArg_EdgeCases", + "TestCommand_StopOnNthArg_WithSubcommands", + "TestCommand_String", + "TestCommand_Timestamp", + "TestCommand_Uint", + "TestCommand_Uint16Slice", + "TestCommand_Uint32Slice", + "TestCommand_Uint64Slice", + "TestCommand_Uint8Slice", + "TestCommand_UintSlice", + "TestCommand_UseShortOptionAfterSliceFlag", + "TestCommand_UseShortOptionHandling", + "TestCommand_UseShortOptionHandlingBoolWithInverse", + "TestCommand_UseShortOptionHandlingCommand", + "TestCommand_UseShortOptionHandlingCommand_missing_value", + "TestCommand_UseShortOptionHandlingMultiByteLastFlag", + "TestCommand_UseShortOptionHandlingSubCommand", + "TestCommand_UseShortOptionHandlingSubCommand_missing_value", + "TestCommand_UseShortOptionHandling_missing_value", + "TestCommand_UseShortOptionWithArg", + "TestCommand_Value", + "TestCommand_Value_InvalidFlagAccessHandler", + "TestCommand_VersionPrinter", + "TestCommand_VisibleCategories", + "TestCommand_VisibleCommands", + "TestCommand_VisibleFlagCategories", + "TestCommand_VisibleSubcCommands", + "TestCommand_Walk", + "TestCommand_Walk_Hidden", + "TestCommand_Walk_NilFn", + "TestCommand_Walk_ShortCircuit", + "TestCommand_lookupFlag", + "TestCompletionAfterDoubleDashDoesNotLeakToNextRun", + "TestCompletionAfterDoubleDashNeverRunsAction", + "TestCompletionBashAppendsSpace", + "TestCompletionBashGreedyColonParsing", + "TestCompletionBashNoShebang", + "TestCompletionBashOmitsPositionalTokenFromDynamicCompletion", + "TestCompletionDisable", + "TestCompletionEnable", + "TestCompletionEnableDiffCommandName", + "TestCompletionFishFormat", + "TestCompletionFishOmitsPositionalTokenFromDynamicCompletion", + "TestCompletionHelp", + "TestCompletionInvalidShell", + "TestCompletionReturnsBeforeError", + "TestCompletionRunsBeforeChain", + "TestCompletionShell", + "TestCompletionShellRenderError", + "TestCompletionShellWriteError", + "TestCompletionSubcommand", + "TestCompletionSubcommandCustomShellComplete", + "TestCompletionSubcommandOrder", + "TestCustomFlagsUnused", + "TestCustomFlagsUsed", + "TestCustomHelpVersionFlags", + "TestCustomUsageCommandHelp", + "TestCustomizedSliceFlagSeparator", + "TestDefaultCommandWithShortFlag", + "TestDefaultCommandWithShortFlagHandling", + "TestDefaultCommandWithSubcommandFlags", + "TestDefaultCompleteWithFlags", + "TestDocGetValue", + "TestDropClashingAliases", + "TestDuplicatePersistentFlagUsesEnvSource", + "TestDurationFlagApply_SetsAllNames", + "TestDurationFlagHelpOutput", + "TestDurationFlagValueFromCommand", + "TestDurationFlagWithEnvVarHelpOutput", + "TestEmptyPositionalArgs", + "TestEmptyPositionalArgsAfterFlag", + "TestEndValue", + "TestEnvHintWindows", + "TestEnvVarValueSource", + "TestEnvVars", + "TestErrRequiredArguments_Error", + "TestErrRequiredFlags_Error", + "TestExtFlag", + "TestExtFlag_SchemaType", + "TestFileHint", + "TestFilePaths", + "TestFileValueSource", + "TestFishCompletion", + "TestFishCompletionBackslashEscaping", + "TestFishCompletionShellComplete", + "TestFlagAction", + "TestFlagActionFromEnv", + "TestFlagActionOrder", + "TestFlagBaseInterfaceValueType", + "TestFlagDefaultValidation", + "TestFlagDefaultValue", + "TestFlagDefaultValueWithEnv", + "TestFlagDuplicates", + "TestFlagEqualsEmptyValue", + "TestFlagMutuallyExclusiveFlags", + "TestFlagSplitMultiValues_Disabled", + "TestFlagStringifying", + "TestFlagValidation", + "TestFlagValue", + "TestFlag_SchemaItemsType_Slice", + "TestFlag_SchemaType_Bool", + "TestFlag_SchemaType_BoolWithInverse", + "TestFlag_SchemaType_Duration", + "TestFlag_SchemaType_Float", + "TestFlag_SchemaType_Generic", + "TestFlag_SchemaType_Int", + "TestFlag_SchemaType_Map", + "TestFlag_SchemaType_NonSliceItemsType", + "TestFlag_SchemaType_PreservesPrecision", + "TestFlag_SchemaType_Slice", + "TestFlag_SchemaType_String", + "TestFlag_SchemaType_Timestamp", + "TestFlag_SchemaType_Uint", + "TestFlagsByName", + "TestFlagsFromEnv", + "TestFloat64FlagApply_SetsAllNames", + "TestFloat64FlagHelpOutput", + "TestFloat64FlagValueFromCommand", + "TestFloat64FlagWithEnvVarHelpOutput", + "TestFloat64SliceFlagApply_DefaultValueWithDestination", + "TestFloat64SliceFlagApply_ParentCommand", + "TestFloat64SliceFlagApply_SetsAllNames", + "TestFloat64SliceFlagApply_UsesEnvValues_noDefault", + "TestFloat64SliceFlagApply_UsesEnvValues_withDefault", + "TestFloat64SliceFlagHelpOutput", + "TestFloat64SliceFlagValueFromCommand", + "TestFloat64SliceFlagWithEnvVarHelpOutput", + "TestGenericFlagApply_SetsAllNames", + "TestGenericFlagHelpOutput", + "TestGenericFlagValueFromCommand", + "TestGenericFlagWithEnvVarHelpOutput", + "TestGenericFlag_SatisfiesDocFlagInterface", + "TestGenericFlag_SatisfiesFlagInterface", + "TestGenericFlag_SatisfiesFmtStringerInterface", + "TestGenericFlag_SatisfiesRequiredFlagInterface", + "TestGenericFlag_SatisfiesVisibleFlagInterface", + "TestGenericValue", + "TestGenericValue_SatisfiesBoolInterface", + "TestHandleExitCoder_Custom", + "TestHandleExitCoder_Default", + "TestHandleExitCoder_ErrorExitCoder", + "TestHandleExitCoder_ErrorFormatter", + "TestHandleExitCoder_ErrorWithFormat", + "TestHandleExitCoder_ExitCoder", + "TestHandleExitCoder_ExitCoderEmptyMessage", + "TestHandleExitCoder_MultiErrorWithExitCoder", + "TestHandleExitCoder_MultiErrorWithFormat", + "TestHandleExitCoder_MultiErrorWithoutExitCoder", + "TestHandleExitCoder_nil", + "TestHasFlags", + "TestHelpCommand_FullName", + "TestHideHelpCommand", + "TestHideHelpCommand_False", + "TestHideHelpCommand_SubcommandCannotOptBackIn", + "TestHideHelpCommand_WithHideHelp", + "TestHideHelpCommand_WithSubcommands", + "TestHideHelp_SubcommandCannotOptBackIn", + "TestInt16Flag", + "TestInt32Flag", + "TestInt64Flag", + "TestInt8Flag", + "TestIntFlag", + "TestIntFlagApply_SetsAllNames", + "TestIntFlagExt", + "TestIntFlagHelpOutput", + "TestIntFlagValueFromCommand", + "TestIntFlagWithEnvVarHelpOutput", + "TestIntSliceFlagApply_DefaultValueWithDestination", + "TestIntSliceFlagApply_ParentContext", + "TestIntSliceFlagApply_SetsAllNames", + "TestIntSliceFlagApply_UsesEnvValues_noDefault", + "TestIntSliceFlagApply_UsesEnvValues_withDefault", + "TestIntSliceFlagHelpOutput", + "TestIntSliceFlagValueFromCommand", + "TestIntSliceFlagWithEnvVarHelpOutput", + "TestIntSliceFlag_SetFromParentCommand", + "TestIntSlice_Serialized_Set", + "TestJSONExportCommand", + "TestJaroWinkler", + "TestLexicographicLess", + "TestLocalFlagError", + "TestLocalSliceFlagAccumulation", + "TestMapValueSource", + "TestMapValueSourceStringer", + "TestMissingRequiredArgDoesNotMutateValue", + "TestMultiErrorErrorsCopy", + "TestMutexFlagCategory", + "TestMutuallyExclusiveFlags", + "TestMutuallyExclusiveFlags_PropagateStringer", + "TestMutuallyExclusiveFlags_PropagateStringerNil", + "TestMutuallyExclusiveFlags_PropagateStringerNilResetsToDefault", + "TestMutuallyExclusiveFlags_PropagateStringerSkipsNonImplementor", + "TestMutuallyExclusiveFlags_StringerInHelpOutput", + "TestNIndent", + "TestNonStringMap", + "TestParseAndRunShortOpts", + "TestParseBoolFromEnv", + "TestParseBoolShortOptionHandle", + "TestParseDestinationBool", + "TestParseDestinationFloat64", + "TestParseDestinationInt", + "TestParseDestinationString", + "TestParseGenericFromEnv", + "TestParseMultiBool", + "TestParseMultiBoolFromEnv", + "TestParseMultiBoolFromEnvCascade", + "TestParseMultiBoolT", + "TestParseMultiFloat64", + "TestParseMultiFloat64FromEnv", + "TestParseMultiFloat64FromEnvCascade", + "TestParseMultiFloat64SliceFromEnv", + "TestParseMultiFloat64SliceFromEnvCascade", + "TestParseMultiFloat64SliceWithDestinationAndEnv", + "TestParseMultiInt", + "TestParseMultiIntFromEnv", + "TestParseMultiIntFromEnvCascade", + "TestParseMultiIntSlice", + "TestParseMultiIntSliceFromEnv", + "TestParseMultiIntSliceFromEnvCascade", + "TestParseMultiIntSliceFromEnvWithDefaults", + "TestParseMultiIntSliceWithDefaults", + "TestParseMultiIntSliceWithDefaultsUnset", + "TestParseMultiIntSliceWithDestinationAndEnv", + "TestParseMultiString", + "TestParseMultiStringFromEnv", + "TestParseMultiStringFromEnvCascade", + "TestParseMultiStringSlice", + "TestParseMultiStringSliceFromEnv", + "TestParseMultiStringSliceFromEnvCascade", + "TestParseMultiStringSliceFromEnvCascadeWithDefaults", + "TestParseMultiStringSliceFromEnvWithDefaults", + "TestParseMultiStringSliceFromEnvWithDestination", + "TestParseMultiStringSliceWithDefaults", + "TestParseMultiStringSliceWithDefaultsUnset", + "TestParseMultiStringSliceWithDestination", + "TestParseMultiStringSliceWithDestinationAndEnv", + "TestParseShortOptionBoolError", + "TestParseShortOptionIntError", + "TestPartialFlagCompletionAfterDoubleDash", + "TestPartialFlagCompletionAfterPositionalArgument", + "TestPartialFlagCompletionDisabled", + "TestPartialFlagCustomCompletionArgs", + "TestPersistentFlag", + "TestPersistentFlagIsSet", + "TestPrintHelpCustomTemplateError", + "TestRequiredArgAfterMultiValueArgUsesRequiredErrorHandling", + "TestRequiredArgAfterOptionalArg", + "TestRequiredArgWithOnUsageError", + "TestRequiredFlagCommandRunBehavior", + "TestRequiredFlagDelayed", + "TestRequiredPersistentFlag", + "TestRunWithNoOsArgs", + "TestSetupInitializesBothWriters", + "TestSetupInitializesOnlyNilWriters", + "TestShellCompletionForIncompleteFlags", + "TestShorthandCommand", + "TestShowCommandHelpAndExit", + "TestShowCommandHelp_AppendHelp", + "TestShowCommandHelp_CommandAliases", + "TestShowCommandHelp_Customtemplate", + "TestShowCommandHelp_HelpPrinter", + "TestShowCommandHelp_HelpPrinterCustom", + "TestShowRootCommandHelpAndExit", + "TestShowRootCommandHelp_CommandAliases", + "TestShowRootCommandHelp_CommandMultiLine_UsageText", + "TestShowRootCommandHelp_CustomAppTemplate", + "TestShowRootCommandHelp_HelpPrinter", + "TestShowRootCommandHelp_HelpPrinterCustom", + "TestShowRootCommandHelp_HiddenCommand", + "TestShowRootCommandHelp_MultiLine_UsageText", + "TestShowRootCommandHelp_UsageText", + "TestShowSubcommandHelpAndExit", + "TestShowSubcommandHelp_CommandAliases", + "TestShowSubcommandHelp_CommandUsageText", + "TestShowSubcommandHelp_GlobalOptions", + "TestShowSubcommandHelp_GlobalOptions_HideHelpCommand", + "TestShowSubcommandHelp_InheritedPersistentOptions", + "TestShowSubcommandHelp_MultiLine_CommandUsageText", + "TestShowSubcommandHelp_MultiLine_SubcommandUsageText", + "TestShowSubcommandHelp_SubcommandUsageText", + "TestSingleOptionalArg", + "TestSingleRequiredArg", + "TestSliceShortOptionHandle", + "TestSliceStringFlagParsing", + "TestSliceValuesNil", + "TestStringFlagApply_SetsAllNames", + "TestStringFlagDefaultText", + "TestStringFlagHelpOutput", + "TestStringFlagTerminator", + "TestStringFlagValueFromCommand", + "TestStringFlagWithEnvVarHelpOutput", + "TestStringMapFlagApply_DefaultValueWithDestination", + "TestStringMapFlagApply_Error", + "TestStringMapFlagApply_SetsAllNames", + "TestStringMapFlagApply_UsesEnvValues_noDefault", + "TestStringMapFlagApply_UsesEnvValues_withDefault", + "TestStringMapFlagHelpOutput", + "TestStringMapFlagTrimsKeyLikeValue", + "TestStringMapFlagValueFromCommand", + "TestStringMapFlagWithEnvVarHelpOutput", + "TestStringMap_Serialized_Set", + "TestStringSliceFlagApply_DefaultValueWithDestination", + "TestStringSliceFlagApply_LocalPreservesRepeatedValues", + "TestStringSliceFlagApply_SetsAllNames", + "TestStringSliceFlagApply_UsesEnvValues_noDefault", + "TestStringSliceFlagApply_UsesEnvValues_withDefault", + "TestStringSliceFlagHelpOutput", + "TestStringSliceFlagValueFromCommand", + "TestStringSliceFlagWithEnvVarHelpOutput", + "TestStringSlice_Serialized_Set", + "TestSubcommandInheritsRootWriters", + "TestSuggestCommand", + "TestSuggestFlag", + "TestSuggestFlagFromError", + "TestSuggestFlagFromErrorNoSuggestion", + "TestSuggestFlagFromErrorWrongCommand", + "TestSuggestFlagFromErrorWrongError", + "TestSuggestFlagHideHelp", + "TestTemplateError", + "TestTextFlagDefaultValue", + "TestTextFlagDestination", + "TestTextFlagFromEnvSource", + "TestTextFlagInvalidValue", + "TestTextFlagSetFromArg", + "TestTextFlagTextNotAvailable", + "TestTextFlagTrimSpace", + "TestTextFlagValueFromCommand", + "TestTextValueSetNilDestination", + "TestTextValueString", + "TestTextValueToString", + "TestTimestampFlagApplyValue", + "TestTimestampFlagApply_Fail_Parse_Wrong_Layout", + "TestTimestampFlagApply_Fail_Parse_Wrong_Time", + "TestTimestampFlagApply_MultipleFormats", + "TestTimestampFlagApply_ShortenedLayouts", + "TestTimestampFlagApply_SingleFormat", + "TestTimestampFlagApply_Timezoned", + "TestTimestampFlagApply_WithDestination", + "TestTimestampFlagApply_YearlessLayoutJanuaryFirst", + "TestTimestampFlagHelpOutput", + "TestTimestampFlagValueFromCommand", + "TestTimestamp_set", + "TestTracing", + "TestUint16Flag", + "TestUint32Flag", + "TestUint64Flag", + "TestUint64FlagHelpOutput", + "TestUint64FlagValueFromCommand", + "TestUint64FlagWithEnvVarHelpOutput", + "TestUint64SliceFlagApply_DefaultValueWithDestination", + "TestUint64SliceFlagApply_ParentCommand", + "TestUint64SliceFlagApply_ParentContext", + "TestUint64SliceFlagApply_SetsAllNames", + "TestUint64SliceFlagApply_UsesEnvValues_noDefault", + "TestUint64SliceFlagApply_UsesEnvValues_withDefault", + "TestUint64SliceFlagHelpOutput", + "TestUint64SliceFlagWithEnvVarHelpOutput", + "TestUint64SliceFlag_ReturnNil", + "TestUint64SliceFlag_SetFromParentCommand", + "TestUint64Slice_Serialized_Set", + "TestUint8Flag", + "TestUintFlag", + "TestUintFlagExt", + "TestUintFlagHelpOutput", + "TestUintFlagValueFromCommand", + "TestUintFlagWithEnvVarHelpOutput", + "TestUintSliceFlagApply_DefaultValueWithDestination", + "TestUintSliceFlagApply_SetsAllNames", + "TestUintSliceFlagApply_UsesEnvValues_noDefault", + "TestUintSliceFlagApply_UsesEnvValues_withDefault", + "TestUintSliceFlagHelpOutput", + "TestUintSliceFlagWithEnvVarHelpOutput", + "TestUintSliceFlag_ReturnNil", + "TestUintSliceFlag_SetFromParentCommand", + "TestUintSlice_Serialized_Set", + "TestUnboundedArgs", + "TestUnquoteUsage", + "TestValueSourceChain", + "TestValueSourceChainEnvKeys", + "TestVersionFlagWorksWhenAliasYieldedToUserFlag", + "TestWhenExitSubCommandWithCodeThenCommandQuitUnexpectedly", + "TestWrap", + "TestWrapLine", + "TestWrappedCommandHelp", + "TestWrappedHelp", + "TestWrappedHelpSubcommand", + "TestWrappedSubcommandHelp", + "TestZeroValueCommand", + "TestZeroValueMutexFlag", + "TestZeroValueSourceChain", + "Test_Float32Flag", + "Test_Float64Flag", + "Test_FloatFlag", + "Test_HelpCommand_ParsesFlags", + "Test_HelpCommand_RequiredFlagsNoDefault", + "Test_HelpFlag_RequiredFlagsNoDefault", + "Test_Help_Custom_Flags", + "Test_Help_Nil_Flags", + "Test_ShowRootCommandHelp_HideVersion", + "Test_ShowRootCommandHelp_MultiLineDescription", + "Test_ShowRootCommandHelp_NoAuthor", + "Test_ShowRootCommandHelp_NoVersion", + "Test_Version_Custom_Flags", + "Test_checkShellCompleteFlag", + "Test_floatValue_String", + "Test_getNumberSlice_float64", + "Test_getNumberSlice_int64", + "Test_helpCommand_Action_ErrorIfNoTopic", + "Test_helpCommand_HideHelpCommand", + "Test_helpCommand_HideHelpFlag", + "Test_helpCommand_InHelpOutput", + "Test_helpSubcommand_Action_ErrorIfNoTopic" + ], + "test_modules": [], + "pass_to_pass": [ + "TestArgNotSet", + "TestArgUsage", + "TestArgsConsumedByNamedArguments", + "TestArgsFloatSliceTypes", + "TestArgsFloatTypes", + "TestArgsIntSliceTypes", + "TestArgsIntTypes", + "TestArgsMaxNotSet", + "TestArgsMinGtMax", + "TestArgsUintSliceTypes", + "TestArgsUintTypes", + "TestArgsUsage", + "TestArgumentRequiredUsageInCommandHelp", + "TestArgumentsInvalidType", + "TestArgumentsRootCommand", + "TestArgumentsSubcommand", + "TestBoolFlagApply_SetsAllNames", + "TestBoolFlagApply_SetsCount", + "TestBoolFlagCountFromCommand", + "TestBoolFlagHelpOutput", + "TestBoolFlagTerminator", + "TestBoolFlagValueFromCommand", + "TestBoolInverseFlagDefaultValidation", + "TestBoolInverseFlagValidation", + "TestBoolWithInverseAction", + "TestBoolWithInverseAlias", + "TestBoolWithInverseBasic", + "TestBoolWithInverseDefaultText", + "TestBoolWithInverseDestination", + "TestBoolWithInverseEnvVars", + "TestBoolWithInverseFlagCount", + "TestBoolWithInverseFlagStringNoPanicWithNoTabStringer", + "TestBoolWithInverseFlag_SatisfiesRequiredFlagInterface", + "TestBoolWithInverseFlag_SatisfiesVisibleFlagInterface", + "TestBoolWithInverseNames", + "TestBoolWithInverseRequired", + "TestBoolWithInverseString", + "TestBoolWithInverseWithPrefix", + "TestCategorizedHelp", + "TestChainedRequiredArgs", + "TestCheckRequiredArgumentsSkipsHelpAndCompletionCommands", + "TestCheckRequiredFlags", + "TestCheckRequiredFlagsWithOnUsageError", + "TestCliArgContainsFlag", + "TestCommandAttributeAccessing", + "TestCommandCategories", + "TestCommandFlagParsing", + "TestCommandHelpPrinter", + "TestCommandHelpSuggest", + "TestCommandInvalidName", + "TestCommandMapKeyValueFlagSeparator", + "TestCommandNoHelpFlag", + "TestCommandReadArgsFromStdIn", + "TestCommandSkipFlagParsing", + "TestCommandSliceFlagSeparator", + "TestCommandSliceFlagSeparatorFromEnvVar", + "TestCommandStringDashOption", + "TestCommand_AfterFunc", + "TestCommand_AfterNotCalledOnSubcommandHelp", + "TestCommand_AfterStillCalledOnNormalSubcommand", + "TestCommand_ArgValidator_ErrorShortCircuitsAction", + "TestCommand_ArgValidator_InheritsFromParent", + "TestCommand_ArgValidator_RunsBeforeAction", + "TestCommand_ArgValidator_RunsBeforeBefore", + "TestCommand_ArgValidator_SubcommandOverride", + "TestCommand_Args", + "TestCommand_BareDash", + "TestCommand_BeforeFunc", + "TestCommand_BeforeFuncPersistentFlag", + "TestCommand_Bool", + "TestCommand_CanAddVFlagOnSubCommands", + "TestCommand_Command", + "TestCommand_CommandNotFound", + "TestCommand_CommandWithDash", + "TestCommand_CommandWithFlagBeforeTerminator", + "TestCommand_CommandWithNoFlagBeforeTerminator", + "TestCommand_DefaultStdin", + "TestCommand_DefaultStdout", + "TestCommand_Deprecated", + "TestCommand_DeprecatedStillRuns", + "TestCommand_Duration", + "TestCommand_EqualsFlagValueValidation", + "TestCommand_ExclusiveFlags", + "TestCommand_ExclusiveFlagsPersistent", + "TestCommand_ExclusiveFlagsWithAfter", + "TestCommand_ExclusiveFlagsWithOnUsageError", + "TestCommand_FlagValuesKeepWhitespace", + "TestCommand_FlagsFromExtPackage", + "TestCommand_Float32Slice", + "TestCommand_Float64", + "TestCommand_Float64Flag", + "TestCommand_Float64Slice", + "TestCommand_FloatSlice", + "TestCommand_HelpFlagTakesPrecedenceOverParseErrors", + "TestCommand_IncorrectUsageOnMutuallyExclusiveFlagsViaRun", + "TestCommand_IncorrectUsageOnRequiredFlagsViaRun", + "TestCommand_IncorrectUsageOnSubcommandWithFailingShowCommandHelp", + "TestCommand_Int", + "TestCommand_Int16Slice", + "TestCommand_Int32Slice", + "TestCommand_Int64Slice", + "TestCommand_Int8Slice", + "TestCommand_IntSlice", + "TestCommand_IsSet", + "TestCommand_IsSet_fromEnv", + "TestCommand_NoDefaultCmdArgMatchingFlag", + "TestCommand_NumFlags", + "TestCommand_OnUsageError_WithSubcommand", + "TestCommand_OnUsageError_WithWrongFlagValue", + "TestCommand_OnUsageError_WithWrongFlagValue_ForSubcommand", + "TestCommand_OnUsageError_hasCommandContext", + "TestCommand_OrderOfOperations", + "TestCommand_ParallelRun", + "TestCommand_ParentCommand_Set", + "TestCommand_ParseSliceFlags", + "TestCommand_ParseSliceFlagsWithMissingValue", + "TestCommand_Path", + "TestCommand_PositionalArgsKeepWhitespace", + "TestCommand_Run", + "TestCommand_RunDefaultCommand", + "TestCommand_RunDefaultCommandWithFlags", + "TestCommand_RunDefaultCommandWithSubCommand", + "TestCommand_RunSubcommandWithDefault", + "TestCommand_Run_BeforeReturnNewContext", + "TestCommand_Run_BeforeReturnNewContextSubcommand", + "TestCommand_Run_BeforeSavesMetadata", + "TestCommand_Run_Categories", + "TestCommand_Run_CommandWithSubcommandHasHelpTopic", + "TestCommand_Run_CustomFlagCanUseVersionAlias", + "TestCommand_Run_CustomShellCompleteAcceptsMalformedFlags", + "TestCommand_Run_DoesNotOverwriteErrorFromBefore", + "TestCommand_Run_FlagActionContext", + "TestCommand_Run_Help", + "TestCommand_Run_SubcommandDoesNotOverwriteErrorFromBefore", + "TestCommand_Run_SubcommandFullPath", + "TestCommand_Run_SubcommandsCanUseErrWriter", + "TestCommand_Run_Version", + "TestCommand_Set", + "TestCommand_SetStdin", + "TestCommand_SetStdin_Subcommand", + "TestCommand_SetStdout", + "TestCommand_Set_InvalidFlagAccessHandler", + "TestCommand_Setup_defaultsReader", + "TestCommand_Setup_defaultsWriter", + "TestCommand_SingleRuneUnicodeFlag", + "TestCommand_SkipFlagParsing", + "TestCommand_StopOnNthArg", + "TestCommand_StopOnNthArg_EdgeCases", + "TestCommand_StopOnNthArg_WithSubcommands", + "TestCommand_String", + "TestCommand_Timestamp", + "TestCommand_Uint", + "TestCommand_Uint16Slice", + "TestCommand_Uint32Slice", + "TestCommand_Uint64Slice", + "TestCommand_Uint8Slice", + "TestCommand_UintSlice", + "TestCommand_UseShortOptionAfterSliceFlag", + "TestCommand_UseShortOptionHandling", + "TestCommand_UseShortOptionHandlingBoolWithInverse", + "TestCommand_UseShortOptionHandlingCommand", + "TestCommand_UseShortOptionHandlingCommand_missing_value", + "TestCommand_UseShortOptionHandlingMultiByteLastFlag", + "TestCommand_UseShortOptionHandlingSubCommand", + "TestCommand_UseShortOptionHandlingSubCommand_missing_value", + "TestCommand_UseShortOptionHandling_missing_value", + "TestCommand_UseShortOptionWithArg", + "TestCommand_Value", + "TestCommand_Value_InvalidFlagAccessHandler", + "TestCommand_VersionPrinter", + "TestCommand_VisibleCategories", + "TestCommand_VisibleCommands", + "TestCommand_VisibleFlagCategories", + "TestCommand_VisibleSubcCommands", + "TestCommand_Walk", + "TestCommand_Walk_Hidden", + "TestCommand_Walk_NilFn", + "TestCommand_Walk_ShortCircuit", + "TestCommand_lookupFlag", + "TestCompletionAfterDoubleDashDoesNotLeakToNextRun", + "TestCompletionAfterDoubleDashNeverRunsAction", + "TestCompletionBashAppendsSpace", + "TestCompletionBashGreedyColonParsing", + "TestCompletionBashNoShebang", + "TestCompletionBashOmitsPositionalTokenFromDynamicCompletion", + "TestCompletionDisable", + "TestCompletionEnable", + "TestCompletionEnableDiffCommandName", + "TestCompletionFishFormat", + "TestCompletionFishOmitsPositionalTokenFromDynamicCompletion", + "TestCompletionHelp", + "TestCompletionInvalidShell", + "TestCompletionReturnsBeforeError", + "TestCompletionRunsBeforeChain", + "TestCompletionShell", + "TestCompletionShellRenderError", + "TestCompletionShellWriteError", + "TestCompletionSubcommand", + "TestCompletionSubcommandCustomShellComplete", + "TestCompletionSubcommandOrder", + "TestCustomFlagsUnused", + "TestCustomFlagsUsed", + "TestCustomHelpVersionFlags", + "TestCustomUsageCommandHelp", + "TestCustomizedSliceFlagSeparator", + "TestDefaultCommandWithShortFlag", + "TestDefaultCommandWithShortFlagHandling", + "TestDefaultCommandWithSubcommandFlags", + "TestDefaultCompleteWithFlags", + "TestDocGetValue", + "TestDropClashingAliases", + "TestDuplicatePersistentFlagUsesEnvSource", + "TestDurationFlagApply_SetsAllNames", + "TestDurationFlagHelpOutput", + "TestDurationFlagValueFromCommand", + "TestDurationFlagWithEnvVarHelpOutput", + "TestEmptyPositionalArgs", + "TestEmptyPositionalArgsAfterFlag", + "TestEndValue", + "TestEnvHintWindows", + "TestEnvVarValueSource", + "TestEnvVars", + "TestErrRequiredArguments_Error", + "TestErrRequiredFlags_Error", + "TestExtFlag", + "TestExtFlag_SchemaType", + "TestFileHint", + "TestFilePaths", + "TestFileValueSource", + "TestFishCompletion", + "TestFishCompletionBackslashEscaping", + "TestFishCompletionShellComplete", + "TestFlagAction", + "TestFlagActionFromEnv", + "TestFlagActionOrder", + "TestFlagBaseInterfaceValueType", + "TestFlagDefaultValidation", + "TestFlagDefaultValue", + "TestFlagDefaultValueWithEnv", + "TestFlagDuplicates", + "TestFlagEqualsEmptyValue", + "TestFlagMutuallyExclusiveFlags", + "TestFlagSplitMultiValues_Disabled", + "TestFlagStringifying", + "TestFlagValidation", + "TestFlag_SchemaItemsType_Slice", + "TestFlag_SchemaType_Bool", + "TestFlag_SchemaType_BoolWithInverse", + "TestFlag_SchemaType_Duration", + "TestFlag_SchemaType_Float", + "TestFlag_SchemaType_Generic", + "TestFlag_SchemaType_Int", + "TestFlag_SchemaType_Map", + "TestFlag_SchemaType_NonSliceItemsType", + "TestFlag_SchemaType_PreservesPrecision", + "TestFlag_SchemaType_Slice", + "TestFlag_SchemaType_String", + "TestFlag_SchemaType_Timestamp", + "TestFlag_SchemaType_Uint", + "TestFlagsByName", + "TestFlagsFromEnv", + "TestFloat64FlagApply_SetsAllNames", + "TestFloat64FlagHelpOutput", + "TestFloat64FlagValueFromCommand", + "TestFloat64FlagWithEnvVarHelpOutput", + "TestFloat64SliceFlagApply_DefaultValueWithDestination", + "TestFloat64SliceFlagApply_ParentCommand", + "TestFloat64SliceFlagApply_SetsAllNames", + "TestFloat64SliceFlagApply_UsesEnvValues_noDefault", + "TestFloat64SliceFlagApply_UsesEnvValues_withDefault", + "TestFloat64SliceFlagHelpOutput", + "TestFloat64SliceFlagValueFromCommand", + "TestFloat64SliceFlagWithEnvVarHelpOutput", + "TestGenericFlagApply_SetsAllNames", + "TestGenericFlagHelpOutput", + "TestGenericFlagValueFromCommand", + "TestGenericFlagWithEnvVarHelpOutput", + "TestGenericFlag_SatisfiesDocFlagInterface", + "TestGenericFlag_SatisfiesFlagInterface", + "TestGenericFlag_SatisfiesFmtStringerInterface", + "TestGenericFlag_SatisfiesRequiredFlagInterface", + "TestGenericFlag_SatisfiesVisibleFlagInterface", + "TestGenericValue", + "TestGenericValue_SatisfiesBoolInterface", + "TestHandleExitCoder_Custom", + "TestHandleExitCoder_Default", + "TestHandleExitCoder_ErrorExitCoder", + "TestHandleExitCoder_ErrorFormatter", + "TestHandleExitCoder_ErrorWithFormat", + "TestHandleExitCoder_ExitCoder", + "TestHandleExitCoder_ExitCoderEmptyMessage", + "TestHandleExitCoder_MultiErrorWithExitCoder", + "TestHandleExitCoder_MultiErrorWithFormat", + "TestHandleExitCoder_MultiErrorWithoutExitCoder", + "TestHandleExitCoder_nil", + "TestHasFlags", + "TestHelpCommand_FullName", + "TestHideHelpCommand", + "TestHideHelpCommand_False", + "TestHideHelpCommand_SubcommandCannotOptBackIn", + "TestHideHelpCommand_WithHideHelp", + "TestHideHelpCommand_WithSubcommands", + "TestHideHelp_SubcommandCannotOptBackIn", + "TestInt16Flag", + "TestInt32Flag", + "TestInt64Flag", + "TestInt8Flag", + "TestIntFlag", + "TestIntFlagApply_SetsAllNames", + "TestIntFlagExt", + "TestIntFlagHelpOutput", + "TestIntFlagValueFromCommand", + "TestIntFlagWithEnvVarHelpOutput", + "TestIntSliceFlagApply_DefaultValueWithDestination", + "TestIntSliceFlagApply_ParentContext", + "TestIntSliceFlagApply_SetsAllNames", + "TestIntSliceFlagApply_UsesEnvValues_noDefault", + "TestIntSliceFlagApply_UsesEnvValues_withDefault", + "TestIntSliceFlagHelpOutput", + "TestIntSliceFlagValueFromCommand", + "TestIntSliceFlagWithEnvVarHelpOutput", + "TestIntSliceFlag_SetFromParentCommand", + "TestIntSlice_Serialized_Set", + "TestJSONExportCommand", + "TestJaroWinkler", + "TestLexicographicLess", + "TestLocalFlagError", + "TestLocalSliceFlagAccumulation", + "TestMapValueSource", + "TestMapValueSourceStringer", + "TestMissingRequiredArgDoesNotMutateValue", + "TestMultiErrorErrorsCopy", + "TestMutexFlagCategory", + "TestMutuallyExclusiveFlags", + "TestMutuallyExclusiveFlags_PropagateStringer", + "TestMutuallyExclusiveFlags_PropagateStringerNil", + "TestMutuallyExclusiveFlags_PropagateStringerNilResetsToDefault", + "TestMutuallyExclusiveFlags_PropagateStringerSkipsNonImplementor", + "TestMutuallyExclusiveFlags_StringerInHelpOutput", + "TestNIndent", + "TestNonStringMap", + "TestParseAndRunShortOpts", + "TestParseBoolFromEnv", + "TestParseBoolShortOptionHandle", + "TestParseDestinationBool", + "TestParseDestinationFloat64", + "TestParseDestinationInt", + "TestParseDestinationString", + "TestParseGenericFromEnv", + "TestParseMultiBool", + "TestParseMultiBoolFromEnv", + "TestParseMultiBoolFromEnvCascade", + "TestParseMultiBoolT", + "TestParseMultiFloat64", + "TestParseMultiFloat64FromEnv", + "TestParseMultiFloat64FromEnvCascade", + "TestParseMultiFloat64SliceFromEnv", + "TestParseMultiFloat64SliceFromEnvCascade", + "TestParseMultiFloat64SliceWithDestinationAndEnv", + "TestParseMultiInt", + "TestParseMultiIntFromEnv", + "TestParseMultiIntFromEnvCascade", + "TestParseMultiIntSlice", + "TestParseMultiIntSliceFromEnv", + "TestParseMultiIntSliceFromEnvCascade", + "TestParseMultiIntSliceFromEnvWithDefaults", + "TestParseMultiIntSliceWithDefaults", + "TestParseMultiIntSliceWithDefaultsUnset", + "TestParseMultiIntSliceWithDestinationAndEnv", + "TestParseMultiString", + "TestParseMultiStringFromEnv", + "TestParseMultiStringFromEnvCascade", + "TestParseMultiStringSlice", + "TestParseMultiStringSliceFromEnv", + "TestParseMultiStringSliceFromEnvCascade", + "TestParseMultiStringSliceFromEnvCascadeWithDefaults", + "TestParseMultiStringSliceFromEnvWithDefaults", + "TestParseMultiStringSliceFromEnvWithDestination", + "TestParseMultiStringSliceWithDefaults", + "TestParseMultiStringSliceWithDefaultsUnset", + "TestParseMultiStringSliceWithDestination", + "TestParseMultiStringSliceWithDestinationAndEnv", + "TestParseShortOptionBoolError", + "TestParseShortOptionIntError", + "TestPartialFlagCompletionAfterDoubleDash", + "TestPartialFlagCompletionAfterPositionalArgument", + "TestPartialFlagCompletionDisabled", + "TestPartialFlagCustomCompletionArgs", + "TestPersistentFlag", + "TestPersistentFlagIsSet", + "TestPrintHelpCustomTemplateError", + "TestRequiredArgAfterMultiValueArgUsesRequiredErrorHandling", + "TestRequiredArgAfterOptionalArg", + "TestRequiredArgWithOnUsageError", + "TestRequiredFlagCommandRunBehavior", + "TestRequiredFlagDelayed", + "TestRequiredPersistentFlag", + "TestRunWithNoOsArgs", + "TestSetupInitializesBothWriters", + "TestSetupInitializesOnlyNilWriters", + "TestShellCompletionForIncompleteFlags", + "TestShorthandCommand", + "TestShowCommandHelpAndExit", + "TestShowCommandHelp_AppendHelp", + "TestShowCommandHelp_CommandAliases", + "TestShowCommandHelp_Customtemplate", + "TestShowCommandHelp_HelpPrinter", + "TestShowCommandHelp_HelpPrinterCustom", + "TestShowRootCommandHelpAndExit", + "TestShowRootCommandHelp_CommandAliases", + "TestShowRootCommandHelp_CommandMultiLine_UsageText", + "TestShowRootCommandHelp_CustomAppTemplate", + "TestShowRootCommandHelp_HelpPrinter", + "TestShowRootCommandHelp_HelpPrinterCustom", + "TestShowRootCommandHelp_HiddenCommand", + "TestShowRootCommandHelp_MultiLine_UsageText", + "TestShowRootCommandHelp_UsageText", + "TestShowSubcommandHelpAndExit", + "TestShowSubcommandHelp_CommandAliases", + "TestShowSubcommandHelp_CommandUsageText", + "TestShowSubcommandHelp_GlobalOptions", + "TestShowSubcommandHelp_GlobalOptions_HideHelpCommand", + "TestShowSubcommandHelp_InheritedPersistentOptions", + "TestShowSubcommandHelp_MultiLine_CommandUsageText", + "TestShowSubcommandHelp_MultiLine_SubcommandUsageText", + "TestShowSubcommandHelp_SubcommandUsageText", + "TestSingleOptionalArg", + "TestSingleRequiredArg", + "TestSliceShortOptionHandle", + "TestSliceStringFlagParsing", + "TestSliceValuesNil", + "TestStringFlagApply_SetsAllNames", + "TestStringFlagDefaultText", + "TestStringFlagHelpOutput", + "TestStringFlagTerminator", + "TestStringFlagValueFromCommand", + "TestStringFlagWithEnvVarHelpOutput", + "TestStringMapFlagApply_DefaultValueWithDestination", + "TestStringMapFlagApply_Error", + "TestStringMapFlagApply_SetsAllNames", + "TestStringMapFlagApply_UsesEnvValues_noDefault", + "TestStringMapFlagApply_UsesEnvValues_withDefault", + "TestStringMapFlagHelpOutput", + "TestStringMapFlagTrimsKeyLikeValue", + "TestStringMapFlagValueFromCommand", + "TestStringMapFlagWithEnvVarHelpOutput", + "TestStringMap_Serialized_Set", + "TestStringSliceFlagApply_DefaultValueWithDestination", + "TestStringSliceFlagApply_LocalPreservesRepeatedValues", + "TestStringSliceFlagApply_SetsAllNames", + "TestStringSliceFlagApply_UsesEnvValues_noDefault", + "TestStringSliceFlagApply_UsesEnvValues_withDefault", + "TestStringSliceFlagHelpOutput", + "TestStringSliceFlagValueFromCommand", + "TestStringSliceFlagWithEnvVarHelpOutput", + "TestStringSlice_Serialized_Set", + "TestSubcommandInheritsRootWriters", + "TestSuggestCommand", + "TestSuggestFlag", + "TestSuggestFlagFromError", + "TestSuggestFlagFromErrorNoSuggestion", + "TestSuggestFlagFromErrorWrongCommand", + "TestSuggestFlagFromErrorWrongError", + "TestSuggestFlagHideHelp", + "TestTemplateError", + "TestTextFlagDefaultValue", + "TestTextFlagDestination", + "TestTextFlagFromEnvSource", + "TestTextFlagInvalidValue", + "TestTextFlagSetFromArg", + "TestTextFlagTextNotAvailable", + "TestTextFlagTrimSpace", + "TestTextFlagValueFromCommand", + "TestTextValueSetNilDestination", + "TestTextValueString", + "TestTextValueToString", + "TestTimestampFlagApplyValue", + "TestTimestampFlagApply_Fail_Parse_Wrong_Layout", + "TestTimestampFlagApply_Fail_Parse_Wrong_Time", + "TestTimestampFlagApply_MultipleFormats", + "TestTimestampFlagApply_ShortenedLayouts", + "TestTimestampFlagApply_SingleFormat", + "TestTimestampFlagApply_Timezoned", + "TestTimestampFlagApply_WithDestination", + "TestTimestampFlagApply_YearlessLayoutJanuaryFirst", + "TestTimestampFlagHelpOutput", + "TestTimestampFlagValueFromCommand", + "TestTimestamp_set", + "TestTracing", + "TestUint16Flag", + "TestUint32Flag", + "TestUint64Flag", + "TestUint64FlagHelpOutput", + "TestUint64FlagValueFromCommand", + "TestUint64FlagWithEnvVarHelpOutput", + "TestUint64SliceFlagApply_DefaultValueWithDestination", + "TestUint64SliceFlagApply_ParentCommand", + "TestUint64SliceFlagApply_ParentContext", + "TestUint64SliceFlagApply_SetsAllNames", + "TestUint64SliceFlagApply_UsesEnvValues_noDefault", + "TestUint64SliceFlagApply_UsesEnvValues_withDefault", + "TestUint64SliceFlagHelpOutput", + "TestUint64SliceFlagWithEnvVarHelpOutput", + "TestUint64SliceFlag_ReturnNil", + "TestUint64SliceFlag_SetFromParentCommand", + "TestUint64Slice_Serialized_Set", + "TestUint8Flag", + "TestUintFlag", + "TestUintFlagExt", + "TestUintFlagHelpOutput", + "TestUintFlagValueFromCommand", + "TestUintFlagWithEnvVarHelpOutput", + "TestUintSliceFlagApply_DefaultValueWithDestination", + "TestUintSliceFlagApply_SetsAllNames", + "TestUintSliceFlagApply_UsesEnvValues_noDefault", + "TestUintSliceFlagApply_UsesEnvValues_withDefault", + "TestUintSliceFlagHelpOutput", + "TestUintSliceFlagWithEnvVarHelpOutput", + "TestUintSliceFlag_ReturnNil", + "TestUintSliceFlag_SetFromParentCommand", + "TestUintSlice_Serialized_Set", + "TestUnboundedArgs", + "TestUnquoteUsage", + "TestValueSourceChain", + "TestValueSourceChainEnvKeys", + "TestVersionFlagWorksWhenAliasYieldedToUserFlag", + "TestWhenExitSubCommandWithCodeThenCommandQuitUnexpectedly", + "TestWrap", + "TestWrapLine", + "TestWrappedCommandHelp", + "TestWrappedHelp", + "TestWrappedHelpSubcommand", + "TestWrappedSubcommandHelp", + "TestZeroValueCommand", + "TestZeroValueMutexFlag", + "TestZeroValueSourceChain", + "Test_Float32Flag", + "Test_Float64Flag", + "Test_FloatFlag", + "Test_HelpCommand_ParsesFlags", + "Test_HelpCommand_RequiredFlagsNoDefault", + "Test_HelpFlag_RequiredFlagsNoDefault", + "Test_Help_Custom_Flags", + "Test_Help_Nil_Flags", + "Test_ShowRootCommandHelp_HideVersion", + "Test_ShowRootCommandHelp_MultiLineDescription", + "Test_ShowRootCommandHelp_NoAuthor", + "Test_ShowRootCommandHelp_NoVersion", + "Test_Version_Custom_Flags", + "Test_checkShellCompleteFlag", + "Test_floatValue_String", + "Test_getNumberSlice_float64", + "Test_getNumberSlice_int64", + "Test_helpCommand_Action_ErrorIfNoTopic", + "Test_helpCommand_HideHelpCommand", + "Test_helpCommand_HideHelpFlag", + "Test_helpCommand_InHelpOutput", + "Test_helpSubcommand_Action_ErrorIfNoTopic" + ], + "gold_test_outcomes": { + "run": 560, + "passed": 558, + "failed": [ + "TestCommand_BeforeAfterFuncShellCompletion", + "TestFlagValue" + ] + }, + "validation": { + "gold": { + "resolved": true, + "sites_ok": true, + "green": true, + "n_run": 560 + }, + "empty": { + "resolved": false, + "sites_ok": false, + "missed_sites": 26 + }, + "partial": { + "resolved": false, + "sites_ok": false, + "green": false, + "missed_sites": 1, + "n_run": 0 + } + } +} \ No newline at end of file diff --git a/harness/tasks/e2e/deep__echo__MiddlewareConfigurator_ToMiddleware_add_echo.json b/harness/tasks/e2e/deep__echo__MiddlewareConfigurator_ToMiddleware_add_echo.json new file mode 100644 index 00000000..4964c2c8 --- /dev/null +++ b/harness/tasks/e2e/deep__echo__MiddlewareConfigurator_ToMiddleware_add_echo.json @@ -0,0 +1,1380 @@ +{ + "instance_id": "deep__echo__MiddlewareConfigurator_ToMiddleware_add_echo", + "repo": "labstack/echo", + "lang": "go", + "base_commit": "3d084be9022432c5a5257924c7d74bfc3444b456", + "instruction": "Middleware configurations are turned into middleware without knowing which Echo instance they will serve. Add a required parameter `e *Echo` to the `ToMiddleware` method of the `echo.MiddlewareConfigurator` interface (echo.go), so it becomes `ToMiddleware(e *Echo) (MiddlewareFunc, error)`, and change every configuration type that implements it (every `XxxConfig.ToMiddleware` in the middleware package, as `ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error)`) and every call of `ToMiddleware`, in source and in tests. At each call pass the `*echo.Echo` the middleware is being built for when the calling function has one in scope (in tests this is usually the `e := echo.New()` instance); where there is none (e.g. `toMiddlewareOrPanic`, used by the `XxxWithConfig` constructors, and tests that build middleware without an Echo instance) pass `nil`. Implementations do not have to use the parameter yet and must accept `nil`. Do not keep a parameterless variant. Behavior must not change.", + "shapes": [ + { + "id": "ToMiddleware/0", + "name": "ToMiddleware", + "arity": 0 + } + ], + "source": "seeded", + "site_mode": "shapes", + "gold_tool": "build_deep.py go recipe: declarations by pattern (func (config XxxConfig) ToMiddleware() and the interface line), call sites from go build/go test compile errors (-gcflags=-e), iterated to a clean build; gofmt (go1.25.14 GOTOOLCHAIN=local)", + "change": "add required parameter (interface method: 22 middleware config implementations + callers)", + "notes": "Call-site value: the enclosing function's `e := echo.New()` when present, else nil.", + "kind": "wide", + "patch": "diff --git a/echo.go b/echo.go\nindex 1a86100..f8f7319 100644\n--- a/echo.go\n+++ b/echo.go\n@@ -134,7 +134,7 @@ type MiddlewareFunc func(next HandlerFunc) HandlerFunc\n \n // MiddlewareConfigurator defines interface for creating middleware handlers with possibility to return configuration errors instead of panicking.\n type MiddlewareConfigurator interface {\n-\tToMiddleware() (MiddlewareFunc, error)\n+\tToMiddleware(e *Echo) (MiddlewareFunc, error)\n }\n \n // Validator is the interface that wraps the Validate function.\n@@ -185,7 +185,6 @@ const (\n \t// RouteAny is a special method type that matches any HTTP method in request. Any has lower\n \t// priority that other methods that have been registered with Router to that path.\n \tRouteAny = \"echo_route_any\"\n-\n )\n \n // Headers\ndiff --git a/middleware/basic_auth.go b/middleware/basic_auth.go\nindex 8a9500a..9be9c4e 100644\n--- a/middleware/basic_auth.go\n+++ b/middleware/basic_auth.go\n@@ -94,7 +94,7 @@ func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts BasicAuthConfig to middleware or returns an error for invalid configuration\n-func (config BasicAuthConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config BasicAuthConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Validator == nil {\n \t\treturn nil, errors.New(\"echo basic-auth middleware requires a validator function\")\n \t}\ndiff --git a/middleware/basic_auth_test.go b/middleware/basic_auth_test.go\nindex 4238635..d1de879 100644\n--- a/middleware/basic_auth_test.go\n+++ b/middleware/basic_auth_test.go\n@@ -128,7 +128,7 @@ func TestBasicAuth(t *testing.T) {\n \n \t\t\tconfig := tc.givenConfig\n \n-\t\t\tmw, err := config.ToMiddleware()\n+\t\t\tmw, err := config.ToMiddleware(e)\n \t\t\tassert.NoError(t, err)\n \n \t\t\th := mw(func(c *echo.Context) error {\ndiff --git a/middleware/body_dump.go b/middleware/body_dump.go\nindex 0443a67..a42fd33 100644\n--- a/middleware/body_dump.go\n+++ b/middleware/body_dump.go\n@@ -70,7 +70,7 @@ func BodyDumpWithConfig(config BodyDumpConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts BodyDumpConfig to middleware or returns an error for invalid configuration\n-func (config BodyDumpConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config BodyDumpConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Handler == nil {\n \t\treturn nil, errors.New(\"echo body-dump middleware requires a handler function\")\n \t}\ndiff --git a/middleware/body_dump_test.go b/middleware/body_dump_test.go\nindex e5f6454..52e75be 100644\n--- a/middleware/body_dump_test.go\n+++ b/middleware/body_dump_test.go\n@@ -34,7 +34,7 @@ func TestBodyDump(t *testing.T) {\n \tmw, err := BodyDumpConfig{Handler: func(c *echo.Context, reqBody, resBody []byte, err error) {\n \t\trequestBody = string(reqBody)\n \t\tresponseBody = string(resBody)\n-\t}}.ToMiddleware()\n+\t}}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \tif assert.NoError(t, mw(h)(c)) {\n@@ -57,7 +57,7 @@ func TestBodyDump_skipper(t *testing.T) {\n \t\tHandler: func(c *echo.Context, reqBody, resBody []byte, err error) {\n \t\t\tisCalled = true\n \t\t},\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \treq := httptest.NewRequest(http.MethodPost, \"/\", strings.NewReader(\"{}\"))\n@@ -82,7 +82,7 @@ func TestBodyDump_fails(t *testing.T) {\n \t\treturn errors.New(\"some error\")\n \t}\n \n-\tmw, err := BodyDumpConfig{Handler: func(c *echo.Context, reqBody, resBody []byte, err error) {}}.ToMiddleware()\n+\tmw, err := BodyDumpConfig{Handler: func(c *echo.Context, reqBody, resBody []byte, err error) {}}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -243,7 +243,7 @@ func TestBodyDump_RequestWithinLimit(t *testing.T) {\n \t\t},\n \t\tMaxRequestBytes: 1 * MB, // 1MB limit\n \t\tMaxResponseBytes: 1 * MB,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -273,7 +273,7 @@ func TestBodyDump_RequestExceedsLimit(t *testing.T) {\n \t\t},\n \t\tMaxRequestBytes: limit,\n \t\tMaxResponseBytes: 1 * MB,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -304,7 +304,7 @@ func TestBodyDump_RequestAtExactLimit(t *testing.T) {\n \t\t},\n \t\tMaxRequestBytes: limit,\n \t\tMaxResponseBytes: 1 * MB,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -331,7 +331,7 @@ func TestBodyDump_ResponseWithinLimit(t *testing.T) {\n \t\t},\n \t\tMaxRequestBytes: 1 * MB,\n \t\tMaxResponseBytes: 1 * MB,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -359,7 +359,7 @@ func TestBodyDump_ResponseExceedsLimit(t *testing.T) {\n \t\t},\n \t\tMaxRequestBytes: 1 * MB,\n \t\tMaxResponseBytes: limit,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -394,7 +394,7 @@ func TestBodyDump_ClientGetsFullResponse(t *testing.T) {\n \t\t},\n \t\tMaxRequestBytes: 1 * MB,\n \t\tMaxResponseBytes: 512, // Very small limit\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -426,7 +426,7 @@ func TestBodyDump_BothLimitsSimultaneous(t *testing.T) {\n \t\t},\n \t\tMaxRequestBytes: limit,\n \t\tMaxResponseBytes: limit,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -453,7 +453,7 @@ func TestBodyDump_DefaultConfig(t *testing.T) {\n \tconfig.Handler = func(c *echo.Context, reqBody, resBody []byte, err error) {\n \t\trequestBodyDumped = string(reqBody)\n \t}\n-\tmw, err := config.ToMiddleware()\n+\tmw, err := config.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -483,7 +483,7 @@ func TestBodyDump_LargeRequestDosPrevention(t *testing.T) {\n \t\t},\n \t\tMaxRequestBytes: limit,\n \t\tMaxResponseBytes: 1 * MB,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -514,7 +514,7 @@ func TestBodyDump_LargeResponseDosPrevention(t *testing.T) {\n \t\t},\n \t\tMaxRequestBytes: 1 * MB,\n \t\tMaxResponseBytes: limit,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -543,7 +543,7 @@ func BenchmarkBodyDump_WithLimit(b *testing.B) {\n \t\t},\n \t\tMaxRequestBytes: 1 * MB,\n \t\tMaxResponseBytes: 1 * MB,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \n \tb.ResetTimer()\n \tfor i := 0; i < b.N; i++ {\n@@ -568,7 +568,7 @@ func BenchmarkBodyDump_BufferPooling(b *testing.B) {\n \t\tHandler: func(c *echo.Context, reqBody, resBody []byte, err error) {},\n \t\tMaxRequestBytes: 1 * MB,\n \t\tMaxResponseBytes: 1 * MB,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \n \tb.ReportAllocs()\n \tb.ResetTimer()\ndiff --git a/middleware/body_limit.go b/middleware/body_limit.go\nindex 4f1963e..b6f5067 100644\n--- a/middleware/body_limit.go\n+++ b/middleware/body_limit.go\n@@ -44,7 +44,7 @@ func BodyLimitWithConfig(config BodyLimitConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts BodyLimitConfig to middleware or returns an error for invalid configuration\n-func (config BodyLimitConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config BodyLimitConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSkipper\n \t}\ndiff --git a/middleware/body_limit_test.go b/middleware/body_limit_test.go\nindex 68d904d..c94ceee 100644\n--- a/middleware/body_limit_test.go\n+++ b/middleware/body_limit_test.go\n@@ -29,7 +29,7 @@ func TestBodyLimitConfig_ToMiddleware(t *testing.T) {\n \t}\n \n \t// Based on content length (within limit)\n-\tmw, err := BodyLimitConfig{LimitBytes: 2 * MB}.ToMiddleware()\n+\tmw, err := BodyLimitConfig{LimitBytes: 2 * MB}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\n@@ -39,7 +39,7 @@ func TestBodyLimitConfig_ToMiddleware(t *testing.T) {\n \t}\n \n \t// Based on content read (overlimit)\n-\tmw, err = BodyLimitConfig{LimitBytes: 2}.ToMiddleware()\n+\tmw, err = BodyLimitConfig{LimitBytes: 2}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \the := mw(h)(c).(echo.HTTPStatusCoder)\n \tassert.Equal(t, http.StatusRequestEntityTooLarge, he.StatusCode())\n@@ -50,7 +50,7 @@ func TestBodyLimitConfig_ToMiddleware(t *testing.T) {\n \trec = httptest.NewRecorder()\n \tc = e.NewContext(req, rec)\n \n-\tmw, err = BodyLimitConfig{LimitBytes: 2 * MB}.ToMiddleware()\n+\tmw, err = BodyLimitConfig{LimitBytes: 2 * MB}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \terr = mw(h)(c)\n \tassert.NoError(t, err)\n@@ -62,7 +62,7 @@ func TestBodyLimitConfig_ToMiddleware(t *testing.T) {\n \treq.ContentLength = -1\n \trec = httptest.NewRecorder()\n \tc = e.NewContext(req, rec)\n-\tmw, err = BodyLimitConfig{LimitBytes: 2}.ToMiddleware()\n+\tmw, err = BodyLimitConfig{LimitBytes: 2}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \the = mw(h)(c).(echo.HTTPStatusCoder)\n \tassert.Equal(t, http.StatusRequestEntityTooLarge, he.StatusCode())\n@@ -132,7 +132,7 @@ func TestBodyLimit_skipper(t *testing.T) {\n \t\t\treturn true\n \t\t},\n \t\tLimitBytes: 2,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \thw := []byte(\"Hello, World!\")\ndiff --git a/middleware/compress.go b/middleware/compress.go\nindex 7754d5d..f9fd493 100644\n--- a/middleware/compress.go\n+++ b/middleware/compress.go\n@@ -66,7 +66,7 @@ func GzipWithConfig(config GzipConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts GzipConfig to middleware or returns an error for invalid configuration\n-func (config GzipConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config GzipConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSkipper\n \t}\ndiff --git a/middleware/compress_test.go b/middleware/compress_test.go\nindex 084ffc9..7a7acfb 100644\n--- a/middleware/compress_test.go\n+++ b/middleware/compress_test.go\n@@ -180,7 +180,7 @@ func TestGzip_ErrorReturned(t *testing.T) {\n }\n \n func TestGzipWithConfig_invalidLevel(t *testing.T) {\n-\tmw, err := GzipConfig{Level: 12}.ToMiddleware()\n+\tmw, err := GzipConfig{Level: 12}.ToMiddleware(nil)\n \tassert.EqualError(t, err, \"invalid gzip level\")\n \tassert.Nil(t, mw)\n }\ndiff --git a/middleware/context_timeout.go b/middleware/context_timeout.go\nindex 6846519..3b0386c 100644\n--- a/middleware/context_timeout.go\n+++ b/middleware/context_timeout.go\n@@ -35,7 +35,7 @@ func ContextTimeoutWithConfig(config ContextTimeoutConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts Config to middleware.\n-func (config ContextTimeoutConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config ContextTimeoutConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Timeout == 0 {\n \t\treturn nil, errors.New(\"timeout must be set\")\n \t}\ndiff --git a/middleware/cors.go b/middleware/cors.go\nindex b4ddbd7..3c5214b 100644\n--- a/middleware/cors.go\n+++ b/middleware/cors.go\n@@ -148,7 +148,7 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts CORSConfig to middleware or returns an error for invalid configuration\n-func (config CORSConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config CORSConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \t// Defaults\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSkipper\ndiff --git a/middleware/cors_test.go b/middleware/cors_test.go\nindex cd208fb..9c6e3b9 100644\n--- a/middleware/cors_test.go\n+++ b/middleware/cors_test.go\n@@ -326,9 +326,9 @@ func TestCORSConfig(t *testing.T) {\n \t\t\tvar mw echo.MiddlewareFunc\n \t\t\tvar err error\n \t\t\tif tc.givenConfig != nil {\n-\t\t\t\tmw, err = tc.givenConfig.ToMiddleware()\n+\t\t\t\tmw, err = tc.givenConfig.ToMiddleware(e)\n \t\t\t} else {\n-\t\t\t\tmw, err = CORSConfig{}.ToMiddleware()\n+\t\t\t\tmw, err = CORSConfig{}.ToMiddleware(e)\n \t\t\t}\n \t\t\tif err != nil {\n \t\t\t\tif tc.expectErr != \"\" {\n@@ -700,7 +700,7 @@ func Test_allowOriginFunc(t *testing.T) {\n \t\tc := e.NewContext(req, rec)\n \t\treq.Header.Set(echo.HeaderOrigin, origin)\n \t\treq.Header.Set(echo.HeaderAccessControlRequestMethod, http.MethodGet)\n-\t\tcors, err := CORSConfig{UnsafeAllowOriginFunc: allowOriginFunc}.ToMiddleware()\n+\t\tcors, err := CORSConfig{UnsafeAllowOriginFunc: allowOriginFunc}.ToMiddleware(e)\n \t\tassert.NoError(t, err)\n \n \t\th := cors(func(c *echo.Context) error { return echo.ErrNotFound })\ndiff --git a/middleware/csrf.go b/middleware/csrf.go\nindex 3999a92..7e8bd86 100644\n--- a/middleware/csrf.go\n+++ b/middleware/csrf.go\n@@ -124,7 +124,7 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts CSRFConfig to middleware or returns an error for invalid configuration\n-func (config CSRFConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config CSRFConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \t// Defaults\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultCSRFConfig.Skipper\ndiff --git a/middleware/csrf_test.go b/middleware/csrf_test.go\nindex 1a6b18e..a5aa8ce 100644\n--- a/middleware/csrf_test.go\n+++ b/middleware/csrf_test.go\n@@ -213,7 +213,7 @@ func TestCSRF_tokenExtractors(t *testing.T) {\n \t\t\t\tTokenLookup: tc.whenTokenLookup,\n \t\t\t\tCookieName: tc.whenCookieName,\n \t\t\t}\n-\t\t\tcsrf, err := config.ToMiddleware()\n+\t\t\tcsrf, err := config.ToMiddleware(e)\n \t\t\tif tc.expectToMiddlewareError != \"\" {\n \t\t\t\tassert.EqualError(t, err, tc.expectToMiddlewareError)\n \t\t\t\treturn\n@@ -342,7 +342,7 @@ func TestCSRFWithConfig(t *testing.T) {\n \t\t\t\t}\n \t\t\t}\n \n-\t\t\tmw, err := config.ToMiddleware()\n+\t\t\tmw, err := config.ToMiddleware(e)\n \t\t\tif tc.expectMWError != \"\" {\n \t\t\t\tassert.EqualError(t, err, tc.expectMWError)\n \t\t\t\treturn\n@@ -454,7 +454,7 @@ func TestCSRFWithSameSiteModeNone(t *testing.T) {\n \n \tcsrf, err := CSRFConfig{\n \t\tCookieSameSite: http.SameSiteNoneMode,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \th := csrf(func(c *echo.Context) error {\ndiff --git a/middleware/decompress.go b/middleware/decompress.go\nindex 52febc6..aacf815 100644\n--- a/middleware/decompress.go\n+++ b/middleware/decompress.go\n@@ -63,7 +63,7 @@ func DecompressWithConfig(config DecompressConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts DecompressConfig to middleware or returns an error for invalid configuration\n-func (config DecompressConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config DecompressConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSkipper\n \t}\n@@ -128,7 +128,6 @@ func (config DecompressConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n \t}, nil\n }\n \n-\n // isGzipContentEncoding reports whether Content-Encoding is gzip.\n // Content codings are case-insensitive per RFC 9110 \u00a78.4.1.\n func isGzipContentEncoding(v string) bool {\ndiff --git a/middleware/decompress_test.go b/middleware/decompress_test.go\nindex fadfa7f..bc56543 100644\n--- a/middleware/decompress_test.go\n+++ b/middleware/decompress_test.go\n@@ -67,7 +67,7 @@ func TestDecompressWithConfig_DefaultConfig_noDecode(t *testing.T) {\n \trec := httptest.NewRecorder()\n \tc := e.NewContext(req, rec)\n \n-\th, err := DecompressConfig{}.ToMiddleware()\n+\th, err := DecompressConfig{}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = h(func(c *echo.Context) error {\n@@ -260,7 +260,7 @@ func TestDecompress_WithinLimit(t *testing.T) {\n \trec := httptest.NewRecorder()\n \tc := e.NewContext(req, rec)\n \n-\th, err := DecompressConfig{MaxDecompressedSize: 100 * MB}.ToMiddleware()\n+\th, err := DecompressConfig{MaxDecompressedSize: 100 * MB}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = h(func(c *echo.Context) error {\n@@ -283,7 +283,7 @@ func TestDecompress_ExceedsLimit(t *testing.T) {\n \trec := httptest.NewRecorder()\n \tc := e.NewContext(req, rec)\n \n-\th, err := DecompressConfig{MaxDecompressedSize: 1024}.ToMiddleware() // 1KB limit\n+\th, err := DecompressConfig{MaxDecompressedSize: 1024}.ToMiddleware(e) // 1KB limit\n \tassert.NoError(t, err)\n \n \terr = h(func(c *echo.Context) error {\n@@ -308,7 +308,7 @@ func TestDecompress_AtExactLimit(t *testing.T) {\n \trec := httptest.NewRecorder()\n \tc := e.NewContext(req, rec)\n \n-\th, err := DecompressConfig{MaxDecompressedSize: 1024}.ToMiddleware()\n+\th, err := DecompressConfig{MaxDecompressedSize: 1024}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = h(func(c *echo.Context) error {\n@@ -335,7 +335,7 @@ func TestDecompress_ZipBomb(t *testing.T) {\n \trec := httptest.NewRecorder()\n \tc := e.NewContext(req, rec)\n \n-\th, err := DecompressConfig{MaxDecompressedSize: 1 * MB}.ToMiddleware()\n+\th, err := DecompressConfig{MaxDecompressedSize: 1 * MB}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = h(func(c *echo.Context) error {\n@@ -360,7 +360,7 @@ func TestDecompress_UnlimitedExplicit(t *testing.T) {\n \trec := httptest.NewRecorder()\n \tc := e.NewContext(req, rec)\n \n-\th, err := DecompressConfig{MaxDecompressedSize: -1}.ToMiddleware() // Unlimited\n+\th, err := DecompressConfig{MaxDecompressedSize: -1}.ToMiddleware(e) // Unlimited\n \tassert.NoError(t, err)\n \n \terr = h(func(c *echo.Context) error {\n@@ -383,7 +383,7 @@ func TestDecompress_DefaultLimit(t *testing.T) {\n \tc := e.NewContext(req, rec)\n \n \t// Use zero value which should apply 100MB default\n-\th, err := DecompressConfig{}.ToMiddleware()\n+\th, err := DecompressConfig{}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = h(func(c *echo.Context) error {\n@@ -405,7 +405,7 @@ func TestDecompress_SmallCustomLimit(t *testing.T) {\n \trec := httptest.NewRecorder()\n \tc := e.NewContext(req, rec)\n \n-\th, err := DecompressConfig{MaxDecompressedSize: 1024}.ToMiddleware() // 1KB limit\n+\th, err := DecompressConfig{MaxDecompressedSize: 1024}.ToMiddleware(e) // 1KB limit\n \tassert.NoError(t, err)\n \n \terr = h(func(c *echo.Context) error {\n@@ -428,7 +428,7 @@ func TestDecompress_MultipleReads(t *testing.T) {\n \trec := httptest.NewRecorder()\n \tc := e.NewContext(req, rec)\n \n-\th, err := DecompressConfig{MaxDecompressedSize: 1024}.ToMiddleware() // 1KB limit\n+\th, err := DecompressConfig{MaxDecompressedSize: 1024}.ToMiddleware(e) // 1KB limit\n \tassert.NoError(t, err)\n \n \terr = h(func(c *echo.Context) error {\n@@ -469,7 +469,7 @@ func TestDecompress_LargePayloadDosPrevention(t *testing.T) {\n \trec := httptest.NewRecorder()\n \tc := e.NewContext(req, rec)\n \n-\th, err := DecompressConfig{MaxDecompressedSize: 1 * MB}.ToMiddleware()\n+\th, err := DecompressConfig{MaxDecompressedSize: 1 * MB}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = h(func(c *echo.Context) error {\n@@ -489,7 +489,7 @@ func BenchmarkDecompress_WithLimit(b *testing.B) {\n \tbody := strings.Repeat(\"benchmark data \", 1000) // ~15KB\n \tgz, _ := gzipString(body)\n \n-\th, _ := DecompressConfig{MaxDecompressedSize: 100 * MB}.ToMiddleware()\n+\th, _ := DecompressConfig{MaxDecompressedSize: 100 * MB}.ToMiddleware(e)\n \n \tb.ReportAllocs()\n \tb.ResetTimer()\ndiff --git a/middleware/key_auth.go b/middleware/key_auth.go\nindex 2dcb980..9c8bc81 100644\n--- a/middleware/key_auth.go\n+++ b/middleware/key_auth.go\n@@ -135,7 +135,7 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts KeyAuthConfig to middleware or returns an error for invalid configuration\n-func (config KeyAuthConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config KeyAuthConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultKeyAuthConfig.Skipper\n \t}\ndiff --git a/middleware/key_auth_test.go b/middleware/key_auth_test.go\nindex 49a917e..e57da5f 100644\n--- a/middleware/key_auth_test.go\n+++ b/middleware/key_auth_test.go\n@@ -325,7 +325,7 @@ func TestKeyAuthWithConfig_errors(t *testing.T) {\n \n \tfor _, tc := range testCases {\n \t\tt.Run(tc.name, func(t *testing.T) {\n-\t\t\tmw, err := tc.whenConfig.ToMiddleware()\n+\t\t\tmw, err := tc.whenConfig.ToMiddleware(nil)\n \t\t\tif tc.expectError != \"\" {\n \t\t\t\tassert.Nil(t, mw)\n \t\t\t\tassert.EqualError(t, err, tc.expectError)\ndiff --git a/middleware/method_override.go b/middleware/method_override.go\nindex 17335a9..9548909 100644\n--- a/middleware/method_override.go\n+++ b/middleware/method_override.go\n@@ -46,7 +46,7 @@ func MethodOverrideWithConfig(config MethodOverrideConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts MethodOverrideConfig to middleware or returns an error for invalid configuration\n-func (config MethodOverrideConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config MethodOverrideConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \t// Defaults\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultMethodOverrideConfig.Skipper\ndiff --git a/middleware/method_override_test.go b/middleware/method_override_test.go\nindex 525ad10..78ba36d 100644\n--- a/middleware/method_override_test.go\n+++ b/middleware/method_override_test.go\n@@ -40,7 +40,7 @@ func TestMethodOverride_formParam(t *testing.T) {\n \t}\n \n \t// Override with form parameter\n-\tm, err := MethodOverrideConfig{Getter: MethodFromForm(\"_method\")}.ToMiddleware()\n+\tm, err := MethodOverrideConfig{Getter: MethodFromForm(\"_method\")}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \treq := httptest.NewRequest(http.MethodPost, \"/\", bytes.NewReader([]byte(\"_method=\"+http.MethodDelete)))\n \trec := httptest.NewRecorder()\n@@ -60,7 +60,7 @@ func TestMethodOverride_queryParam(t *testing.T) {\n \t}\n \n \t// Override with query parameter\n-\tm, err := MethodOverrideConfig{Getter: MethodFromQuery(\"_method\")}.ToMiddleware()\n+\tm, err := MethodOverrideConfig{Getter: MethodFromQuery(\"_method\")}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \treq := httptest.NewRequest(http.MethodPost, \"/?_method=\"+http.MethodDelete, nil)\n \trec := httptest.NewRecorder()\ndiff --git a/middleware/middleware.go b/middleware/middleware.go\nindex 4562d03..6a43f7a 100644\n--- a/middleware/middleware.go\n+++ b/middleware/middleware.go\n@@ -89,7 +89,7 @@ func DefaultSkipper(c *echo.Context) bool {\n }\n \n func toMiddlewareOrPanic(config echo.MiddlewareConfigurator) echo.MiddlewareFunc {\n-\tmw, err := config.ToMiddleware()\n+\tmw, err := config.ToMiddleware(nil)\n \tif err != nil {\n \t\tpanic(err)\n \t}\ndiff --git a/middleware/proxy.go b/middleware/proxy.go\nindex 497aefe..e991365 100644\n--- a/middleware/proxy.go\n+++ b/middleware/proxy.go\n@@ -303,7 +303,7 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts ProxyConfig to middleware or returns an error for invalid configuration\n-func (config ProxyConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config ProxyConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultProxyConfig.Skipper\n \t}\ndiff --git a/middleware/rate_limiter.go b/middleware/rate_limiter.go\nindex bd70e10..d9daa04 100644\n--- a/middleware/rate_limiter.go\n+++ b/middleware/rate_limiter.go\n@@ -121,7 +121,7 @@ func RateLimiterWithConfig(config RateLimiterConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts RateLimiterConfig to middleware or returns an error for invalid configuration\n-func (config RateLimiterConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config RateLimiterConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultRateLimiterConfig.Skipper\n \t}\ndiff --git a/middleware/rate_limiter_test.go b/middleware/rate_limiter_test.go\nindex 267e8d0..988f402 100644\n--- a/middleware/rate_limiter_test.go\n+++ b/middleware/rate_limiter_test.go\n@@ -95,7 +95,7 @@ func TestRateLimiterWithConfig(t *testing.T) {\n \t\t\treturn ctx.JSON(http.StatusBadRequest, nil)\n \t\t},\n \t\tStore: inMemoryStore,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \ttestCases := []struct {\n@@ -144,7 +144,7 @@ func TestRateLimiterWithConfig_defaultDenyHandler(t *testing.T) {\n \t\t\treturn id, nil\n \t\t},\n \t\tStore: inMemoryStore,\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \ttestCases := []struct {\n@@ -190,7 +190,7 @@ func TestRateLimiterWithConfig_defaultConfig(t *testing.T) {\n \n \t\tmw, err := RateLimiterConfig{\n \t\t\tStore: inMemoryStore,\n-\t\t}.ToMiddleware()\n+\t\t}.ToMiddleware(e)\n \t\tassert.NoError(t, err)\n \n \t\ttestCases := []struct {\n@@ -252,7 +252,7 @@ func TestRateLimiterWithConfig_skipper(t *testing.T) {\n \t\tIdentifierExtractor: func(ctx *echo.Context) (string, error) {\n \t\t\treturn \"127.0.0.1\", nil\n \t\t},\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(handler)(c)\n@@ -288,7 +288,7 @@ func TestRateLimiterWithConfig_skipperNoSkip(t *testing.T) {\n \t\tIdentifierExtractor: func(ctx *echo.Context) (string, error) {\n \t\t\treturn \"127.0.0.1\", nil\n \t\t},\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \t_ = mw(handler)(c)\n@@ -321,7 +321,7 @@ func TestRateLimiterWithConfig_beforeFunc(t *testing.T) {\n \t\tIdentifierExtractor: func(ctx *echo.Context) (string, error) {\n \t\t\treturn \"127.0.0.1\", nil\n \t\t},\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(handler)(c)\ndiff --git a/middleware/recover.go b/middleware/recover.go\nindex 01fde51..ef2603c 100644\n--- a/middleware/recover.go\n+++ b/middleware/recover.go\n@@ -50,7 +50,7 @@ func RecoverWithConfig(config RecoverConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts RecoverConfig to middleware or returns an error for invalid configuration\n-func (config RecoverConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config RecoverConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \t// Defaults\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultRecoverConfig.Skipper\ndiff --git a/middleware/redirect.go b/middleware/redirect.go\nindex bb7045c..d16c4bb 100644\n--- a/middleware/redirect.go\n+++ b/middleware/redirect.go\n@@ -116,7 +116,7 @@ func NonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts RedirectConfig to middleware or returns an error for invalid configuration\n-func (config RedirectConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config RedirectConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSkipper\n \t}\ndiff --git a/middleware/request_id.go b/middleware/request_id.go\nindex 9d059bc..2bb4552 100644\n--- a/middleware/request_id.go\n+++ b/middleware/request_id.go\n@@ -39,7 +39,7 @@ func RequestIDWithConfig(config RequestIDConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts RequestIDConfig to middleware or returns an error for invalid configuration\n-func (config RequestIDConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config RequestIDConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSkipper\n \t}\ndiff --git a/middleware/request_id_test.go b/middleware/request_id_test.go\nindex 465e6fc..09f3bfd 100644\n--- a/middleware/request_id_test.go\n+++ b/middleware/request_id_test.go\n@@ -106,7 +106,7 @@ func TestRequestIDWithConfig(t *testing.T) {\n \t\treturn c.String(http.StatusOK, \"test\")\n \t}\n \n-\trid, err := RequestIDConfig{}.ToMiddleware()\n+\trid, err := RequestIDConfig{}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \th := rid(handler)\n \th(c)\ndiff --git a/middleware/request_logger.go b/middleware/request_logger.go\nindex 74d0928..8990b10 100644\n--- a/middleware/request_logger.go\n+++ b/middleware/request_logger.go\n@@ -235,7 +235,7 @@ type RequestLoggerValues struct {\n \n // RequestLoggerWithConfig returns a RequestLogger middleware with config.\n func RequestLoggerWithConfig(config RequestLoggerConfig) echo.MiddlewareFunc {\n-\tmw, err := config.ToMiddleware()\n+\tmw, err := config.ToMiddleware(nil)\n \tif err != nil {\n \t\tpanic(err)\n \t}\n@@ -243,7 +243,7 @@ func RequestLoggerWithConfig(config RequestLoggerConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts RequestLoggerConfig into middleware or returns an error for invalid configuration.\n-func (config RequestLoggerConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config RequestLoggerConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSkipper\n \t}\ndiff --git a/middleware/rewrite.go b/middleware/rewrite.go\nindex 02907ca..1b47609 100644\n--- a/middleware/rewrite.go\n+++ b/middleware/rewrite.go\n@@ -51,7 +51,7 @@ func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts RewriteConfig to middleware or returns an error for invalid configuration\n-func (config RewriteConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config RewriteConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSkipper\n \t}\ndiff --git a/middleware/secure.go b/middleware/secure.go\nindex 022cce4..f49243b 100644\n--- a/middleware/secure.go\n+++ b/middleware/secure.go\n@@ -98,7 +98,7 @@ func SecureWithConfig(config SecureConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts SecureConfig to middleware or returns an error for invalid configuration\n-func (config SecureConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config SecureConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \t// Defaults\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSecureConfig.Skipper\ndiff --git a/middleware/secure_test.go b/middleware/secure_test.go\nindex 5ca1308..c687d82 100644\n--- a/middleware/secure_test.go\n+++ b/middleware/secure_test.go\n@@ -50,7 +50,7 @@ func TestSecureWithConfig(t *testing.T) {\n \t\tHSTSMaxAge: 3600,\n \t\tContentSecurityPolicy: \"default-src 'self'\",\n \t\tReferrerPolicy: \"origin\",\n-\t}.ToMiddleware()\n+\t}.ToMiddleware(e)\n \tassert.NoError(t, err)\n \n \terr = mw(h)(c)\ndiff --git a/middleware/slash.go b/middleware/slash.go\nindex d00102c..2d660b0 100644\n--- a/middleware/slash.go\n+++ b/middleware/slash.go\n@@ -36,7 +36,7 @@ func AddTrailingSlashWithConfig(config AddTrailingSlashConfig) echo.MiddlewareFu\n }\n \n // ToMiddleware converts AddTrailingSlashConfig to middleware or returns an error for invalid configuration\n-func (config AddTrailingSlashConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config AddTrailingSlashConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSkipper\n \t}\n@@ -100,7 +100,7 @@ func RemoveTrailingSlashWithConfig(config RemoveTrailingSlashConfig) echo.Middle\n }\n \n // ToMiddleware converts RemoveTrailingSlashConfig to middleware or returns an error for invalid configuration\n-func (config RemoveTrailingSlashConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config RemoveTrailingSlashConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \tif config.Skipper == nil {\n \t\tconfig.Skipper = DefaultSkipper\n \t}\ndiff --git a/middleware/static.go b/middleware/static.go\nindex 200f96a..cebb6b4 100644\n--- a/middleware/static.go\n+++ b/middleware/static.go\n@@ -174,7 +174,7 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc {\n }\n \n // ToMiddleware converts StaticConfig to middleware or returns an error for invalid configuration\n-func (config StaticConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n+func (config StaticConfig) ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error) {\n \t// Defaults\n \tif config.Root == \"\" {\n \t\tconfig.Root = \".\" // For security we want to restrict to CWD.\ndiff --git a/middleware/static_test.go b/middleware/static_test.go\nindex 889169e..ed18086 100644\n--- a/middleware/static_test.go\n+++ b/middleware/static_test.go\n@@ -586,7 +586,7 @@ func TestStatic_CustomFS(t *testing.T) {\n \t\t\t\tconfig.Root = tc.root\n \t\t\t}\n \n-\t\t\tmiddlewareFunc, err := config.ToMiddleware()\n+\t\t\tmiddlewareFunc, err := config.ToMiddleware(e)\n \t\t\tassert.NoError(t, err)\n \n \t\t\te.Use(middlewareFunc)\n@@ -646,7 +646,7 @@ func TestStatic_DirectoryBrowsing(t *testing.T) {\n \t\tt.Run(tc.name, func(t *testing.T) {\n \t\t\te := echo.New()\n \n-\t\t\tmiddlewareFunc, err := tc.givenConfig.ToMiddleware()\n+\t\t\tmiddlewareFunc, err := tc.givenConfig.ToMiddleware(e)\n \t\t\tassert.NoError(t, err)\n \n \t\t\te.Use(middlewareFunc)\n", + "test_patch": "", + "fail_to_pass": [], + "problem_statement": "Middleware configurations are turned into middleware without knowing which Echo instance they will serve. Add a required parameter `e *Echo` to the `ToMiddleware` method of the `echo.MiddlewareConfigurator` interface (echo.go), so it becomes `ToMiddleware(e *Echo) (MiddlewareFunc, error)`, and change every configuration type that implements it (every `XxxConfig.ToMiddleware` in the middleware package, as `ToMiddleware(e *echo.Echo) (echo.MiddlewareFunc, error)`) and every call of `ToMiddleware`, in source and in tests. At each call pass the `*echo.Echo` the middleware is being built for when the calling function has one in scope (in tests this is usually the `e := echo.New()` instance); where there is none (e.g. `toMiddlewareOrPanic`, used by the `XxxWithConfig` constructors, and tests that build middleware without an Echo instance) pass `nil`. Implementations do not have to use the parameter yet and must accept `nil`. Do not keep a parameterless variant. Behavior must not change.", + "prompt_source": "wide-mandate", + "gold_files": [ + "echo.go", + "middleware/basic_auth.go", + "middleware/basic_auth_test.go", + "middleware/body_dump.go", + "middleware/body_dump_test.go", + "middleware/body_limit.go", + "middleware/body_limit_test.go", + "middleware/compress.go", + "middleware/compress_test.go", + "middleware/context_timeout.go", + "middleware/cors.go", + "middleware/cors_test.go", + "middleware/csrf.go", + "middleware/csrf_test.go", + "middleware/decompress.go", + "middleware/decompress_test.go", + "middleware/key_auth.go", + "middleware/key_auth_test.go", + "middleware/method_override.go", + "middleware/method_override_test.go", + "middleware/middleware.go", + "middleware/proxy.go", + "middleware/rate_limiter.go", + "middleware/rate_limiter_test.go", + "middleware/recover.go", + "middleware/redirect.go", + "middleware/request_id.go", + "middleware/request_id_test.go", + "middleware/request_logger.go", + "middleware/rewrite.go", + "middleware/secure.go", + "middleware/secure_test.go", + "middleware/slash.go", + "middleware/static.go", + "middleware/static_test.go" + ], + "base_shape_counts": { + "ToMiddleware/0": { + "echo.go": 1, + "middleware/basic_auth.go": 1, + "middleware/basic_auth_test.go": 1, + "middleware/body_dump.go": 1, + "middleware/body_dump_test.go": 15, + "middleware/body_limit.go": 1, + "middleware/body_limit_test.go": 5, + "middleware/compress.go": 1, + "middleware/compress_test.go": 1, + "middleware/context_timeout.go": 1, + "middleware/cors.go": 1, + "middleware/cors_test.go": 3, + "middleware/csrf.go": 1, + "middleware/csrf_test.go": 3, + "middleware/decompress.go": 1, + "middleware/decompress_test.go": 11, + "middleware/key_auth.go": 1, + "middleware/key_auth_test.go": 1, + "middleware/method_override.go": 1, + "middleware/method_override_test.go": 2, + "middleware/middleware.go": 1, + "middleware/proxy.go": 1, + "middleware/rate_limiter.go": 1, + "middleware/rate_limiter_test.go": 6, + "middleware/recover.go": 1, + "middleware/redirect.go": 1, + "middleware/request_id.go": 1, + "middleware/request_id_test.go": 1, + "middleware/request_logger.go": 2, + "middleware/rewrite.go": 1, + "middleware/secure.go": 1, + "middleware/secure_test.go": 1, + "middleware/slash.go": 2, + "middleware/static.go": 1, + "middleware/static_test.go": 2 + } + }, + "gold_shape_counts": { + "ToMiddleware/0": {} + }, + "gold_sites": 76, + "gold_site_files": 35, + "test_functions": [ + "TestAddTrailingSlash", + "TestAddTrailingSlashWithConfig", + "TestAutoHeadExplicitHeadTakesPrecedence", + "TestBasicAuth", + "TestBasicAuthRealm", + "TestBasicAuthWithConfig_panic", + "TestBasicAuth_panic", + "TestBindCachedMetaPreservesFieldNameError", + "TestBindForm", + "TestBindHeaderParam", + "TestBindHeaderParamBadType", + "TestBindInt8", + "TestBindJSON", + "TestBindMultipartForm", + "TestBindMultipartFormFiles", + "TestBindParam", + "TestBindQueryParams", + "TestBindQueryParamsCaseInsensitive", + "TestBindQueryParamsCaseSensitivePrioritized", + "TestBindSetWithProperType", + "TestBindUnmarshalParam", + "TestBindUnmarshalParamAnonymousFieldPtr", + "TestBindUnmarshalParamAnonymousFieldPtrCustomTag", + "TestBindUnmarshalParamAnonymousFieldPtrNil", + "TestBindUnmarshalParamExtras", + "TestBindUnmarshalParamPtr", + "TestBindUnmarshalParams", + "TestBindUnmarshalText", + "TestBindUnmarshalTextPtr", + "TestBindUnmarshalTypeError", + "TestBindUnsupportedMediaType", + "TestBindWithDelimiter_invalidType", + "TestBindXML", + "TestBind_formConversionErrorIncludesFieldName", + "TestBindbindData", + "TestBindingError_Error", + "TestBindingError_ErrorJSON", + "TestBindingError_marshalJSON_emptyMessageFallsBackToStatusText", + "TestBindingError_serializesToStructuredJSON", + "TestBodyDump", + "TestBodyDumpResponseWriter_CanFlush", + "TestBodyDumpResponseWriter_CanHijack", + "TestBodyDumpResponseWriter_CanNotFlush", + "TestBodyDumpResponseWriter_CanNotHijack", + "TestBodyDumpResponseWriter_CanUnwrap", + "TestBodyDumpWithConfig_panic", + "TestBodyDump_BothLimitsSimultaneous", + "TestBodyDump_ClientGetsFullResponse", + "TestBodyDump_DefaultConfig", + "TestBodyDump_LargeRequestDosPrevention", + "TestBodyDump_LargeResponseDosPrevention", + "TestBodyDump_ReadError", + "TestBodyDump_RequestAtExactLimit", + "TestBodyDump_RequestExceedsLimit", + "TestBodyDump_RequestWithinLimit", + "TestBodyDump_ResponseExceedsLimit", + "TestBodyDump_ResponseWithinLimit", + "TestBodyDump_fails", + "TestBodyDump_panic", + "TestBodyDump_skipper", + "TestBodyLimit", + "TestBodyLimitAfterDecompressUsesDecodedSize", + "TestBodyLimitConfig_ToMiddleware", + "TestBodyLimitReader", + "TestBodyLimitWithConfig", + "TestBodyLimit_skipper", + "TestCORS", + "TestCORSConfig", + "TestCORSWithConfig_AllowMethods", + "TestCORS_NonPreflightOPTIONSPassThrough", + "TestCSRF", + "TestCSRFConfig_checkSecFetchSiteRequest", + "TestCSRFConfig_skipper", + "TestCSRFErrorHandling", + "TestCSRFSetSameSiteMode", + "TestCSRFWithConfig", + "TestCSRFWithSameSiteDefaultMode", + "TestCSRFWithSameSiteModeNone", + "TestCSRFWithoutSameSiteMode", + "TestCSRF_tokenExtractors", + "TestClientCancelConnectionResultsHTTPCode499", + "TestCompressRequestWithoutDecompressMiddleware", + "TestConcurrentRouter_ConcurrentReadWrite", + "TestConcurrentRouter_ConcurrentReads", + "TestConcurrentRouter_ConcurrentWrites", + "TestConcurrentRouter_ParametersNoRace", + "TestConcurrentRouter_Remove", + "TestConcurrentRouter_RoutesIterationDuringModification", + "TestContextAttachment", + "TestContextCookie", + "TestContextEcho", + "TestContextFormFile", + "TestContextFormValue", + "TestContextGet", + "TestContextGetAndSetPathValuesMutability", + "TestContextGetInvalidCast", + "TestContextGetNonExistentKey", + "TestContextGetOK", + "TestContextGetOrInvalidCast", + "TestContextGetOrNonExistentKey", + "TestContextGetOrOK", + "TestContextHTML", + "TestContextHTMLBlob", + "TestContextInline", + "TestContextJSON", + "TestContextJSONBlob", + "TestContextJSONErrorsOut", + "TestContextJSONP", + "TestContextJSONPBlob", + "TestContextJSONPretty", + "TestContextJSONStatusAcrossReset", + "TestContextJSONWithEmptyIntent", + "TestContextJSONWithNotEchoResponse", + "TestContextMultipartForm", + "TestContextNoContent", + "TestContextRedirect", + "TestContextRenderErrorsOnNoRenderer", + "TestContextRenderTemplate", + "TestContextRenderTemplateError", + "TestContextRequest", + "TestContextResetClearsStore", + "TestContextResponse", + "TestContextStream", + "TestContextTimeoutCanHandleContextDeadlineOnNextHandler", + "TestContextTimeoutErrorOutInHandler", + "TestContextTimeoutSkipper", + "TestContextTimeoutSuccessfulRequest", + "TestContextTimeoutTestRequestClone", + "TestContextTimeoutWithDefaultErrorMessage", + "TestContextTimeoutWithTimeout0", + "TestContextXML", + "TestContextXMLBlob", + "TestContextXMLPretty", + "TestContextXMLWithEmptyIntent", + "TestContext_Bind", + "TestContext_File", + "TestContext_FileFS", + "TestContext_IsWebSocket", + "TestContext_JSON_CommitsCustomResponseCode", + "TestContext_PathParam", + "TestContext_PathParamDefault", + "TestContext_PathValues", + "TestContext_QueryParam", + "TestContext_QueryParamDefault", + "TestContext_QueryParams", + "TestContext_QueryString", + "TestContext_RealIP", + "TestContext_Request", + "TestContext_Scheme", + "TestContext_SetParamNamesShouldNotModifyPathValuesCapacity", + "TestContext_Validate", + "TestCorsHeaders", + "TestCreateExtractors", + "TestDecompress", + "TestDecompressContentEncodingCaseInsensitive", + "TestDecompressErrorReturned", + "TestDecompressNoContent", + "TestDecompressPoolError", + "TestDecompressSkipper", + "TestDecompressWithConfig_DefaultConfig", + "TestDecompressWithConfig_DefaultConfig_noDecode", + "TestDecompress_AtExactLimit", + "TestDecompress_DefaultLimit", + "TestDecompress_ExceedsLimit", + "TestDecompress_LargePayloadDosPrevention", + "TestDecompress_MultipleReads", + "TestDecompress_SmallCustomLimit", + "TestDecompress_UnlimitedExplicit", + "TestDecompress_WithinLimit", + "TestDecompress_ZipBomb", + "TestDecompress_skippedIfNoHeader", + "TestDefaultBinder_BindBody", + "TestDefaultBinder_BindToStructFromMixedSources", + "TestDefaultBinder_bindDataToMap", + "TestDefaultHTTPErrorHandler", + "TestDefaultHTTPErrorHandler_CommitedResponse", + "TestDefaultJSONCodec_Decode", + "TestDefaultJSONCodec_Decode_BodyReadError", + "TestDefaultJSONCodec_Decode_LargeBodyThenNormal", + "TestDefaultJSONCodec_Decode_PooledBufferConcurrent", + "TestDefaultJSONCodec_Decode_PooledBufferReuse", + "TestDefaultJSONCodec_Decode_RejectsTrailingData", + "TestDefaultJSONCodec_Encode", + "TestDefaultRouter_AddDuplicateRouteAllowed", + "TestDefaultRouter_AddDuplicateRouteNotAllowed", + "TestDefaultRouter_AddWithoutHandler", + "TestDefaultRouter_MethodNotAllowedHandler", + "TestDefaultRouter_NotFoundHandler", + "TestDefaultRouter_OptionsMethodHandler", + "TestDefaultRouter_PathValuesCanMatchEmptyValues", + "TestDefaultRouter_Remove", + "TestDefaultRouter_UnescapePathParamValues", + "TestDefaultRouter_UseEscapedPathForRouting", + "TestEcho", + "TestEchoConnect", + "TestEchoContext", + "TestEchoDelete", + "TestEchoFile", + "TestEchoGet", + "TestEchoGroup", + "TestEchoHandler", + "TestEchoHead", + "TestEchoMatch", + "TestEchoMethodNotAllowed", + "TestEchoMiddleware", + "TestEchoMiddlewareError", + "TestEchoNotFound", + "TestEchoOptions", + "TestEchoPatch", + "TestEchoPost", + "TestEchoPut", + "TestEchoQuery", + "TestEchoRewritePreMiddleware", + "TestEchoRewriteReplacementEscaping", + "TestEchoRewriteWithCaret", + "TestEchoRewriteWithRegexRules", + "TestEchoServeHTTPPathEncoding", + "TestEchoStaticRedirectIndex", + "TestEchoTrace", + "TestEchoWrapHandler", + "TestEchoWrapMiddleware", + "TestEcho_Any", + "TestEcho_Any_hasLowerPriority", + "TestEcho_Any_matchesArbitraryMethod", + "TestEcho_FileFS", + "TestEcho_OnAddRoute", + "TestEcho_RouteNotFound", + "TestEcho_Start", + "TestEcho_StaticFS", + "TestEcho_StaticPanic", + "TestExtractIPDirect", + "TestExtractIPFromRealIPHeader", + "TestExtractIPFromXFFHeader", + "TestFailNextTarget", + "TestFilepathOrContent", + "TestFormFieldBinder", + "TestFormValue", + "TestFormValueOr", + "TestFormValue_UnsupportedType", + "TestFormValues", + "TestFormValuesOr", + "TestFormValues_UnsupportedType", + "TestFormat", + "TestGetRawQueryParamMatchesStdlib", + "TestGlobalMiddlewareRunsOnNotFoundAndMethodNotAllowed", + "TestGroupFile", + "TestGroupRouteMiddleware", + "TestGroupRouteMiddlewareWithMatchAny", + "TestGroupRoute_automaticOPTIONS", + "TestGroupRoute_catchAllMasksMethodHandling", + "TestGroupRoute_concreteRoutesResolve", + "TestGroupRoute_methodMismatchReturns405", + "TestGroupStaticFS_EncodedSeparatorDoesNotBypassRoute", + "TestGroup_Any", + "TestGroup_CONNECT", + "TestGroup_DELETE", + "TestGroup_FileFS", + "TestGroup_HEAD", + "TestGroup_Match", + "TestGroup_MatchWithErrors", + "TestGroup_OPTIONS", + "TestGroup_PATCH", + "TestGroup_POST", + "TestGroup_PUT", + "TestGroup_QUERY", + "TestGroup_RouteNotFound", + "TestGroup_RouteNotFoundUsesRouterConfig", + "TestGroup_RouteNotFoundWithMiddleware", + "TestGroup_Static", + "TestGroup_StaticMultiTest", + "TestGroup_StaticPanic", + "TestGroup_TRACE", + "TestGroup_UseMultipleTimes", + "TestGroup_doesNotAffectRootRoutes", + "TestGroup_multiLevelGroup", + "TestGroup_withRoutesWillExecuteMiddlewareFor404", + "TestGroup_withoutRouteWillExecuteMiddleware", + "TestGroup_withoutRouteWillNotExecuteMiddleware", + "TestGzipResponseWriter_CanHijack", + "TestGzipResponseWriter_CanNotHijack", + "TestGzipResponseWriter_CanUnwrap", + "TestGzipWithConfig_invalidLevel", + "TestGzipWithMinLength", + "TestGzipWithMinLengthChunked", + "TestGzipWithMinLengthNoContent", + "TestGzipWithMinLengthTooShort", + "TestGzipWithResponseWithoutBody", + "TestGzipWithStatic", + "TestGzip_AcceptEncodingHeader", + "TestGzip_Empty", + "TestGzip_ErrorReturned", + "TestGzip_NoAcceptEncodingHeader", + "TestGzip_NoContent", + "TestGzip_chunked", + "TestHTTPError_Error", + "TestHTTPError_StatusCode", + "TestHTTPError_WrapUnwrap", + "TestHandlerName", + "TestHeadResponseWriter_Commit_NoContentLength_1xx", + "TestHeadResponseWriter_Commit_NoContentLength_204", + "TestHeadResponseWriter_Commit_NoContentLength_304", + "TestHeadResponseWriter_Commit_NoContentLength_TransferEncoding", + "TestHeadResponseWriter_Commit_NoWriteHeader_WhenNotCommitted", + "TestHeadResponseWriter_Commit_PreservesExplicitContentLength", + "TestHeadResponseWriter_Commit_SetsContentLength", + "TestHeadResponseWriter_Flush_IsNoop", + "TestHeadResponseWriter_Header_DelegatesToUnderlying", + "TestHeadResponseWriter_Hijack_DelegatesToUnderlying", + "TestHeadResponseWriter_Unwrap_ReturnsUnderlying", + "TestHeadResponseWriter_WriteHeader_FirstCallWins", + "TestHeadResponseWriter_WriteHeader_SetsCommittedOnUnderlying", + "TestHeadResponseWriter_Write_CountsBytes", + "TestHeadResponseWriter_Write_ImpliesStatus200", + "TestHeadResponseWriter_Write_MultipleCallsSumBytes", + "TestIPChecker_TrustOption", + "TestIsCORSPreflight", + "TestKeyAuth", + "TestKeyAuthWithConfig", + "TestKeyAuthWithConfig_errors", + "TestKeyAuth_errorHandlerSwallowsError", + "TestLegacyIPExtractor", + "TestLogger", + "TestMethodNotAllowedAndNotFound", + "TestMethodOverride", + "TestMethodOverride_formParam", + "TestMethodOverride_ignoreGet", + "TestMethodOverride_queryParam", + "TestMiddlewares", + "TestModifyResponseUseContext", + "TestMustGzipWithConfig_panics", + "TestMustKeyAuthWithConfig_panic", + "TestMustProxyWithConfig_emptyBalancerPanics", + "TestMustRateLimiterWithConfig_panicBehaviour", + "TestMustRequestIDWithConfig_RequestIDHandler", + "TestMustRequestIDWithConfig_customGenerator", + "TestMustRequestIDWithConfig_skipper", + "TestMustRewriteWithConfig_emptyRulesPanics", + "TestMustRewriteWithConfig_skipper", + "TestMustStaticWithConfig_panicsInvalidDirListTemplate", + "TestNestedJSONUsesFreshDelayedWriter", + "TestNewDefaultFS", + "TestNewHTTPError", + "TestNewRateLimiterMemoryStore", + "TestNewWithConfig", + "TestNonWWWRedirectWithConfig", + "TestParseValue_BindUnmarshaler", + "TestParseValue_Duration", + "TestParseValue_JSONUnmarshaler", + "TestParseValue_OptionsOnlyForTime", + "TestParseValue_TextUnmarshaler", + "TestParseValue_Time", + "TestParseValue_bool", + "TestParseValue_float32", + "TestParseValue_float64", + "TestParseValue_int", + "TestParseValue_int16", + "TestParseValue_int32", + "TestParseValue_int64", + "TestParseValue_int8", + "TestParseValue_string", + "TestParseValue_uint", + "TestParseValue_uint16", + "TestParseValue_uint32", + "TestParseValue_uint64", + "TestParseValue_uint8", + "TestParseValues_bools", + "TestPathParam", + "TestPathParamOr", + "TestPathParam_UnsupportedType", + "TestPathValuesBinder", + "TestPathValuesSizeOverMultipleRequests", + "TestPathValues_Get", + "TestPathValues_GetOr", + "TestPreMiddlewares", + "TestProblemDetailsHTTPErrorHandler", + "TestProblemDetailsHTTPErrorHandler_CommittedResponse", + "TestProblemDetailsHTTPErrorHandler_DoesNotMutateSharedProblem", + "TestProblemError_Error", + "TestProblemError_StatusCode", + "TestProxy", + "TestProxyError", + "TestProxyErrorHandler", + "TestProxyRealIPHeader", + "TestProxyRetries", + "TestProxyRetryWithBackendTimeout", + "TestProxyRewrite", + "TestProxyRewriteRegex", + "TestProxyWebSocketXForwardedFor", + "TestProxyWithConfigWebSocketNonTLS2NonTLS", + "TestProxyWithConfigWebSocketNonTLS2TLS", + "TestProxyWithConfigWebSocketTLS2NonTLS", + "TestProxyWithConfigWebSocketTLS2TLS", + "TestProxyWithNoTargetDoesNotRetry", + "TestProxyWithNoTargetReturnsBadGateway", + "TestQueryParam", + "TestQueryParamOr", + "TestQueryParam_UnsupportedType", + "TestQueryParams", + "TestQueryParamsBinder_FailFast", + "TestQueryParamsOr", + "TestQueryParams_UnsupportedType", + "TestRandomBalancerWithNoTargets", + "TestRandomString", + "TestRandomStringBias", + "TestRandomStringConcurrent", + "TestRateLimiter", + "TestRateLimiterMemoryStore_Allow", + "TestRateLimiterMemoryStore_AllowContextSetsHeaders", + "TestRateLimiterMemoryStore_ConcurrentAccess", + "TestRateLimiterMemoryStore_FractionalRateDefaultBurst", + "TestRateLimiterMemoryStore_RaceDetection", + "TestRateLimiterMemoryStore_TOCTOUFix", + "TestRateLimiterMemoryStore_TimeOrdering", + "TestRateLimiterMemoryStore_cleanupStaleVisitors", + "TestRateLimiterWithConfig", + "TestRateLimiterWithConfig_beforeFunc", + "TestRateLimiterWithConfig_defaultConfig", + "TestRateLimiterWithConfig_defaultDenyHandler", + "TestRateLimiterWithConfig_skipper", + "TestRateLimiterWithConfig_skipperNoSkip", + "TestRateLimiter_storeAllowContextIsPreferred", + "TestRecover", + "TestRecoverErrAbortHandler", + "TestRecoverWithConfig", + "TestRecover_skipper", + "TestRedirectHTTPSNonWWWRedirect", + "TestRedirectHTTPSRedirect", + "TestRedirectHTTPSWWWRedirect", + "TestRedirectNonWWWRedirect", + "TestRedirectWWWRedirect", + "TestRemoveTrailingSlash", + "TestRemoveTrailingSlashWithConfig", + "TestRenderWithTemplateRenderer", + "TestRequestID", + "TestRequestIDConfigDifferentHeader", + "TestRequestIDWithConfig", + "TestRequestID_IDNotAltered", + "TestRequestLoggerError", + "TestRequestLoggerOK", + "TestRequestLoggerWithConfig", + "TestRequestLoggerWithConfig_missingOnLogValuesPanics", + "TestRequestLogger_HandleError", + "TestRequestLogger_ID", + "TestRequestLogger_LogValuesFuncError", + "TestRequestLogger_allFields", + "TestRequestLogger_beforeNextFunc", + "TestRequestLogger_headerIsCaseInsensitive", + "TestRequestLogger_logError", + "TestRequestLogger_skipper", + "TestResolveResponseStatus", + "TestResponse", + "TestResponse_ChangeStatusCodeBeforeWrite", + "TestResponse_Flush", + "TestResponse_FlushPanics", + "TestResponse_Unwrap", + "TestResponse_UnwrapResponse", + "TestResponse_UnwrapResponse_error", + "TestResponse_Write_FallsBackToDefaultStatus", + "TestResponse_Write_UsesSetResponseCode", + "TestResponse_isHijacker", + "TestRewriteAfterRouting", + "TestRewriteURL", + "TestRewriteWithConfigPreMiddleware_Issue1143", + "TestRoundRobinBalancerWithNoTargets", + "TestRouteInfo", + "TestRouteInfo_Reverse", + "TestRouteMultiLevelBacktracking", + "TestRouteMultiLevelBacktracking2", + "TestRoute_ForGroup", + "TestRoute_ToRouteInfo", + "TestRouterAllowHeaderForAnyOtherMethodType", + "TestRouterAnyMatchesLastAddedAnyRoute", + "TestRouterAutoHandleHEADFullHTTPHandlerFlow", + "TestRouterAutoHandleHEAD_204Response", + "TestRouterAutoHandleHEAD_304Response", + "TestRouterAutoHandleHEAD_AnyRoute_NotWrapped", + "TestRouterAutoHandleHEAD_CatchAllRoute", + "TestRouterAutoHandleHEAD_ContentType", + "TestRouterAutoHandleHEAD_CustomResponseHeaders", + "TestRouterAutoHandleHEAD_ExplicitContentLength", + "TestRouterAutoHandleHEAD_HandlerError_ErrorHandlerRuns", + "TestRouterAutoHandleHEAD_MultipleWriteCalls", + "TestRouterAutoHandleHEAD_NoGetRoute_Returns405", + "TestRouterAutoHandleHEAD_PathParams", + "TestRouterAutoHandleHEAD_TransferEncoding", + "TestRouterAutoHandleHEAD_WithMiddleware", + "TestRouterBacktrackingFromMultipleParamKinds", + "TestRouterFillsRequestPatternField", + "TestRouterFindNotPanicOrLoopsWhenContextSetParamValuesIsCalledWithLessValuesThanEchoMaxParam", + "TestRouterGitHubAPI", + "TestRouterHandleMethodOptions", + "TestRouterIssue1348", + "TestRouterMatchAny", + "TestRouterMatchAnyMultiLevel", + "TestRouterMatchAnyMultiLevelWithPost", + "TestRouterMatchAnyPrefixIssue", + "TestRouterMatchAnySlash", + "TestRouterMicroParam", + "TestRouterMixParamMatchAny", + "TestRouterMixedParams", + "TestRouterMultiRoute", + "TestRouterNoRoutablePath", + "TestRouterOptionsMethodHandler", + "TestRouterPanicWhenParamNoRootOnlyChildsFailsFind", + "TestRouterParam", + "TestRouterParam1466", + "TestRouterParamAlias", + "TestRouterParamBacktraceNotFound", + "TestRouterParamNames", + "TestRouterParamOrdering", + "TestRouterParamStaticConflict", + "TestRouterParamWithSlash", + "TestRouterParam_escapeColon", + "TestRouterPriority", + "TestRouterPriorityNotFound", + "TestRouterStatic", + "TestRouterStaticDynamicConflict", + "TestRouterTwoParam", + "TestRouter_Match_DifferentParamNamesForSamePlace", + "TestRouter_ReverseNotFound", + "TestRouter_RouteWhenNotFoundRouteAnyKind", + "TestRouter_RouteWhenNotFoundRouteParamKind", + "TestRouter_RouteWhenNotFoundRouteStaticKind", + "TestRouter_RouteWhenNotFoundRouteWithNodeSplitting", + "TestRouter_Routes", + "TestRouter_addAndMatchAllSupportedMethods", + "TestRouter_addEmptyPathToSlashReverse", + "TestRoutes_Clone", + "TestRoutes_FilterByMethod", + "TestRoutes_FilterByName", + "TestRoutes_FilterByPath", + "TestRoutes_FindByMethodPath", + "TestRoutes_Reverse", + "TestRoutes_ReverseHandlerName", + "TestSecure", + "TestSecureWithConfig", + "TestSecureWithConfig_CSPReportOnly", + "TestSecureWithConfig_HSTSExcludeSubdomains", + "TestSecureWithConfig_HSTSPreloadEnabled", + "TestStartConfig_GracefulShutdown", + "TestStartConfig_Start", + "TestStartConfig_StartTLS", + "TestStartConfig_Start_createListenerError", + "TestStartConfig_WithBeforeServeFunc", + "TestStartConfig_WithHTTP2WithCustomTlsConfig", + "TestStartConfig_WithHideBanner", + "TestStartConfig_WithHidePort", + "TestStartConfig_WithListenerNetwork", + "TestStatic", + "TestStaticDirectoryHandlerAndRouterInconsistentEscaping", + "TestStaticDirectoryHandler_EncodedSeparatorDoesNotBypassRoute", + "TestStaticHTML5PreservesMatchedHandlerNotFound", + "TestStaticMiddlewareAndRouterInconsistentEscaping", + "TestStatic_CustomFS", + "TestStatic_DirectoryBrowsing", + "TestStatic_EncodedSeparatorDoesNotBypassRoute", + "TestStatic_percentEncodedTraversalIsBlocked", + "TestStatic_servesFileWithPercentInName", + "TestStatic_useCaseForApiAndSPAs", + "TestStatusCode", + "TestTargetProvider", + "TestTestRequestLogger", + "TestTimeFormatBinding", + "TestToMultipleFields", + "TestTrustIPRange", + "TestTrustLinkLocal", + "TestTrustLoopback", + "TestTrustPrivateNet", + "TestValidateOrigins", + "TestValueBinder_BindError", + "TestValueBinder_BindUnmarshaler", + "TestValueBinder_BindWithDelimiter", + "TestValueBinder_BindWithDelimiter_types", + "TestValueBinder_Bool", + "TestValueBinder_Bools", + "TestValueBinder_CustomFunc", + "TestValueBinder_CustomFuncWithError", + "TestValueBinder_Duration", + "TestValueBinder_DurationError", + "TestValueBinder_Durations", + "TestValueBinder_DurationsError", + "TestValueBinder_Float32", + "TestValueBinder_Float32s", + "TestValueBinder_Float64", + "TestValueBinder_Float64s", + "TestValueBinder_GetValues", + "TestValueBinder_Int64_intValue", + "TestValueBinder_Int64s_intsValue", + "TestValueBinder_Int_Types", + "TestValueBinder_Int_errorMessage", + "TestValueBinder_Ints_Types", + "TestValueBinder_Ints_Types_FailFast", + "TestValueBinder_JSONUnmarshaler", + "TestValueBinder_MustCustomFunc", + "TestValueBinder_String", + "TestValueBinder_Strings", + "TestValueBinder_TextUnmarshaler", + "TestValueBinder_Time", + "TestValueBinder_TimeError", + "TestValueBinder_Times", + "TestValueBinder_TimesError", + "TestValueBinder_Uint64_uintValue", + "TestValueBinder_Uint64s_uintsValue", + "TestValueBinder_UnixTime", + "TestValueBinder_UnixTimeMilli", + "TestValueBinder_UnixTimeNano", + "TestValueBinder_errorStopsBinding", + "TestValuesFromCookie", + "TestValuesFromForm", + "TestValuesFromHeader", + "TestValuesFromParam", + "TestValuesFromQuery", + "TestVirtualHostHandler", + "TestWrapHeadHandler_HandlerPanic_OriginalWriterRestored", + "TestWrapHeadHandler_PreservesCustomResponseHeaders", + "TestWrapHeadHandler_PropagatesHandlerError", + "TestWrapHeadHandler_RestoresOriginalWriterAfterHandler", + "TestWrapHeadHandler_RouteLevelMiddlewareSeesTrueCommitted", + "TestWrapHeadHandler_SuppressesBodyWrittenByHandler", + "Test_allowOriginFunc", + "Test_allowOriginScheme", + "Test_matchScheme" + ], + "test_modules": [], + "pass_to_pass": [ + "TestAddTrailingSlash", + "TestAddTrailingSlashWithConfig", + "TestAutoHeadExplicitHeadTakesPrecedence", + "TestBasicAuth", + "TestBasicAuthRealm", + "TestBasicAuthWithConfig_panic", + "TestBasicAuth_panic", + "TestBindCachedMetaPreservesFieldNameError", + "TestBindForm", + "TestBindHeaderParam", + "TestBindHeaderParamBadType", + "TestBindInt8", + "TestBindJSON", + "TestBindMultipartForm", + "TestBindMultipartFormFiles", + "TestBindParam", + "TestBindQueryParams", + "TestBindQueryParamsCaseInsensitive", + "TestBindQueryParamsCaseSensitivePrioritized", + "TestBindSetWithProperType", + "TestBindUnmarshalParam", + "TestBindUnmarshalParamAnonymousFieldPtr", + "TestBindUnmarshalParamAnonymousFieldPtrCustomTag", + "TestBindUnmarshalParamAnonymousFieldPtrNil", + "TestBindUnmarshalParamExtras", + "TestBindUnmarshalParamPtr", + "TestBindUnmarshalParams", + "TestBindUnmarshalText", + "TestBindUnmarshalTextPtr", + "TestBindUnmarshalTypeError", + "TestBindUnsupportedMediaType", + "TestBindWithDelimiter_invalidType", + "TestBindXML", + "TestBind_formConversionErrorIncludesFieldName", + "TestBindbindData", + "TestBindingError_Error", + "TestBindingError_ErrorJSON", + "TestBindingError_marshalJSON_emptyMessageFallsBackToStatusText", + "TestBindingError_serializesToStructuredJSON", + "TestBodyDump", + "TestBodyDumpResponseWriter_CanFlush", + "TestBodyDumpResponseWriter_CanHijack", + "TestBodyDumpResponseWriter_CanNotFlush", + "TestBodyDumpResponseWriter_CanNotHijack", + "TestBodyDumpResponseWriter_CanUnwrap", + "TestBodyDumpWithConfig_panic", + "TestBodyDump_BothLimitsSimultaneous", + "TestBodyDump_ClientGetsFullResponse", + "TestBodyDump_DefaultConfig", + "TestBodyDump_LargeRequestDosPrevention", + "TestBodyDump_LargeResponseDosPrevention", + "TestBodyDump_ReadError", + "TestBodyDump_RequestAtExactLimit", + "TestBodyDump_RequestExceedsLimit", + "TestBodyDump_RequestWithinLimit", + "TestBodyDump_ResponseExceedsLimit", + "TestBodyDump_ResponseWithinLimit", + "TestBodyDump_fails", + "TestBodyDump_panic", + "TestBodyDump_skipper", + "TestBodyLimit", + "TestBodyLimitAfterDecompressUsesDecodedSize", + "TestBodyLimitConfig_ToMiddleware", + "TestBodyLimitReader", + "TestBodyLimitWithConfig", + "TestBodyLimit_skipper", + "TestCORS", + "TestCORSConfig", + "TestCORSWithConfig_AllowMethods", + "TestCORS_NonPreflightOPTIONSPassThrough", + "TestCSRF", + "TestCSRFConfig_checkSecFetchSiteRequest", + "TestCSRFConfig_skipper", + "TestCSRFErrorHandling", + "TestCSRFSetSameSiteMode", + "TestCSRFWithConfig", + "TestCSRFWithSameSiteDefaultMode", + "TestCSRFWithSameSiteModeNone", + "TestCSRFWithoutSameSiteMode", + "TestCSRF_tokenExtractors", + "TestClientCancelConnectionResultsHTTPCode499", + "TestCompressRequestWithoutDecompressMiddleware", + "TestConcurrentRouter_ConcurrentReadWrite", + "TestConcurrentRouter_ConcurrentReads", + "TestConcurrentRouter_ConcurrentWrites", + "TestConcurrentRouter_ParametersNoRace", + "TestConcurrentRouter_Remove", + "TestConcurrentRouter_RoutesIterationDuringModification", + "TestContextAttachment", + "TestContextCookie", + "TestContextEcho", + "TestContextFormFile", + "TestContextFormValue", + "TestContextGet", + "TestContextGetAndSetPathValuesMutability", + "TestContextGetInvalidCast", + "TestContextGetNonExistentKey", + "TestContextGetOK", + "TestContextGetOrInvalidCast", + "TestContextGetOrNonExistentKey", + "TestContextGetOrOK", + "TestContextHTML", + "TestContextHTMLBlob", + "TestContextInline", + "TestContextJSON", + "TestContextJSONBlob", + "TestContextJSONErrorsOut", + "TestContextJSONP", + "TestContextJSONPBlob", + "TestContextJSONPretty", + "TestContextJSONStatusAcrossReset", + "TestContextJSONWithEmptyIntent", + "TestContextJSONWithNotEchoResponse", + "TestContextMultipartForm", + "TestContextNoContent", + "TestContextRedirect", + "TestContextRenderErrorsOnNoRenderer", + "TestContextRenderTemplate", + "TestContextRenderTemplateError", + "TestContextRequest", + "TestContextResetClearsStore", + "TestContextResponse", + "TestContextStream", + "TestContextTimeoutCanHandleContextDeadlineOnNextHandler", + "TestContextTimeoutErrorOutInHandler", + "TestContextTimeoutSkipper", + "TestContextTimeoutSuccessfulRequest", + "TestContextTimeoutTestRequestClone", + "TestContextTimeoutWithDefaultErrorMessage", + "TestContextTimeoutWithTimeout0", + "TestContextXML", + "TestContextXMLBlob", + "TestContextXMLPretty", + "TestContextXMLWithEmptyIntent", + "TestContext_Bind", + "TestContext_File", + "TestContext_FileFS", + "TestContext_IsWebSocket", + "TestContext_JSON_CommitsCustomResponseCode", + "TestContext_PathParam", + "TestContext_PathParamDefault", + "TestContext_PathValues", + "TestContext_QueryParam", + "TestContext_QueryParamDefault", + "TestContext_QueryParams", + "TestContext_QueryString", + "TestContext_RealIP", + "TestContext_Request", + "TestContext_Scheme", + "TestContext_SetParamNamesShouldNotModifyPathValuesCapacity", + "TestContext_Validate", + "TestCorsHeaders", + "TestCreateExtractors", + "TestDecompress", + "TestDecompressContentEncodingCaseInsensitive", + "TestDecompressErrorReturned", + "TestDecompressNoContent", + "TestDecompressPoolError", + "TestDecompressSkipper", + "TestDecompressWithConfig_DefaultConfig", + "TestDecompressWithConfig_DefaultConfig_noDecode", + "TestDecompress_AtExactLimit", + "TestDecompress_DefaultLimit", + "TestDecompress_ExceedsLimit", + "TestDecompress_LargePayloadDosPrevention", + "TestDecompress_MultipleReads", + "TestDecompress_SmallCustomLimit", + "TestDecompress_UnlimitedExplicit", + "TestDecompress_WithinLimit", + "TestDecompress_ZipBomb", + "TestDecompress_skippedIfNoHeader", + "TestDefaultBinder_BindBody", + "TestDefaultBinder_BindToStructFromMixedSources", + "TestDefaultBinder_bindDataToMap", + "TestDefaultHTTPErrorHandler", + "TestDefaultHTTPErrorHandler_CommitedResponse", + "TestDefaultJSONCodec_Decode", + "TestDefaultJSONCodec_Decode_BodyReadError", + "TestDefaultJSONCodec_Decode_LargeBodyThenNormal", + "TestDefaultJSONCodec_Decode_PooledBufferConcurrent", + "TestDefaultJSONCodec_Decode_PooledBufferReuse", + "TestDefaultJSONCodec_Decode_RejectsTrailingData", + "TestDefaultJSONCodec_Encode", + "TestDefaultRouter_AddDuplicateRouteAllowed", + "TestDefaultRouter_AddDuplicateRouteNotAllowed", + "TestDefaultRouter_AddWithoutHandler", + "TestDefaultRouter_MethodNotAllowedHandler", + "TestDefaultRouter_NotFoundHandler", + "TestDefaultRouter_OptionsMethodHandler", + "TestDefaultRouter_PathValuesCanMatchEmptyValues", + "TestDefaultRouter_Remove", + "TestDefaultRouter_UnescapePathParamValues", + "TestDefaultRouter_UseEscapedPathForRouting", + "TestEcho", + "TestEchoConnect", + "TestEchoContext", + "TestEchoDelete", + "TestEchoFile", + "TestEchoGet", + "TestEchoGroup", + "TestEchoHandler", + "TestEchoHead", + "TestEchoMatch", + "TestEchoMethodNotAllowed", + "TestEchoMiddleware", + "TestEchoMiddlewareError", + "TestEchoNotFound", + "TestEchoOptions", + "TestEchoPatch", + "TestEchoPost", + "TestEchoPut", + "TestEchoQuery", + "TestEchoRewritePreMiddleware", + "TestEchoRewriteReplacementEscaping", + "TestEchoRewriteWithCaret", + "TestEchoRewriteWithRegexRules", + "TestEchoServeHTTPPathEncoding", + "TestEchoStaticRedirectIndex", + "TestEchoTrace", + "TestEchoWrapHandler", + "TestEchoWrapMiddleware", + "TestEcho_Any", + "TestEcho_Any_hasLowerPriority", + "TestEcho_Any_matchesArbitraryMethod", + "TestEcho_FileFS", + "TestEcho_OnAddRoute", + "TestEcho_RouteNotFound", + "TestEcho_Start", + "TestEcho_StaticFS", + "TestEcho_StaticPanic", + "TestExtractIPDirect", + "TestExtractIPFromRealIPHeader", + "TestExtractIPFromXFFHeader", + "TestFailNextTarget", + "TestFilepathOrContent", + "TestFormFieldBinder", + "TestFormValue", + "TestFormValueOr", + "TestFormValue_UnsupportedType", + "TestFormValues", + "TestFormValuesOr", + "TestFormValues_UnsupportedType", + "TestFormat", + "TestGetRawQueryParamMatchesStdlib", + "TestGlobalMiddlewareRunsOnNotFoundAndMethodNotAllowed", + "TestGroupFile", + "TestGroupRouteMiddleware", + "TestGroupRouteMiddlewareWithMatchAny", + "TestGroupRoute_automaticOPTIONS", + "TestGroupRoute_catchAllMasksMethodHandling", + "TestGroupRoute_concreteRoutesResolve", + "TestGroupRoute_methodMismatchReturns405", + "TestGroupStaticFS_EncodedSeparatorDoesNotBypassRoute", + "TestGroup_Any", + "TestGroup_CONNECT", + "TestGroup_DELETE", + "TestGroup_FileFS", + "TestGroup_HEAD", + "TestGroup_Match", + "TestGroup_MatchWithErrors", + "TestGroup_OPTIONS", + "TestGroup_PATCH", + "TestGroup_POST", + "TestGroup_PUT", + "TestGroup_QUERY", + "TestGroup_RouteNotFound", + "TestGroup_RouteNotFoundUsesRouterConfig", + "TestGroup_RouteNotFoundWithMiddleware", + "TestGroup_Static", + "TestGroup_StaticMultiTest", + "TestGroup_StaticPanic", + "TestGroup_TRACE", + "TestGroup_UseMultipleTimes", + "TestGroup_doesNotAffectRootRoutes", + "TestGroup_multiLevelGroup", + "TestGroup_withRoutesWillExecuteMiddlewareFor404", + "TestGroup_withoutRouteWillExecuteMiddleware", + "TestGroup_withoutRouteWillNotExecuteMiddleware", + "TestGzipResponseWriter_CanHijack", + "TestGzipResponseWriter_CanNotHijack", + "TestGzipResponseWriter_CanUnwrap", + "TestGzipWithConfig_invalidLevel", + "TestGzipWithMinLength", + "TestGzipWithMinLengthChunked", + "TestGzipWithMinLengthNoContent", + "TestGzipWithMinLengthTooShort", + "TestGzipWithResponseWithoutBody", + "TestGzipWithStatic", + "TestGzip_AcceptEncodingHeader", + "TestGzip_Empty", + "TestGzip_ErrorReturned", + "TestGzip_NoAcceptEncodingHeader", + "TestGzip_NoContent", + "TestGzip_chunked", + "TestHTTPError_Error", + "TestHTTPError_StatusCode", + "TestHTTPError_WrapUnwrap", + "TestHandlerName", + "TestHeadResponseWriter_Commit_NoContentLength_1xx", + "TestHeadResponseWriter_Commit_NoContentLength_204", + "TestHeadResponseWriter_Commit_NoContentLength_304", + "TestHeadResponseWriter_Commit_NoContentLength_TransferEncoding", + "TestHeadResponseWriter_Commit_NoWriteHeader_WhenNotCommitted", + "TestHeadResponseWriter_Commit_PreservesExplicitContentLength", + "TestHeadResponseWriter_Commit_SetsContentLength", + "TestHeadResponseWriter_Flush_IsNoop", + "TestHeadResponseWriter_Header_DelegatesToUnderlying", + "TestHeadResponseWriter_Hijack_DelegatesToUnderlying", + "TestHeadResponseWriter_Unwrap_ReturnsUnderlying", + "TestHeadResponseWriter_WriteHeader_FirstCallWins", + "TestHeadResponseWriter_WriteHeader_SetsCommittedOnUnderlying", + "TestHeadResponseWriter_Write_CountsBytes", + "TestHeadResponseWriter_Write_ImpliesStatus200", + "TestHeadResponseWriter_Write_MultipleCallsSumBytes", + "TestIPChecker_TrustOption", + "TestIsCORSPreflight", + "TestKeyAuth", + "TestKeyAuthWithConfig", + "TestKeyAuthWithConfig_errors", + "TestKeyAuth_errorHandlerSwallowsError", + "TestLegacyIPExtractor", + "TestLogger", + "TestMethodNotAllowedAndNotFound", + "TestMethodOverride", + "TestMethodOverride_formParam", + "TestMethodOverride_ignoreGet", + "TestMethodOverride_queryParam", + "TestMiddlewares", + "TestModifyResponseUseContext", + "TestMustGzipWithConfig_panics", + "TestMustKeyAuthWithConfig_panic", + "TestMustProxyWithConfig_emptyBalancerPanics", + "TestMustRateLimiterWithConfig_panicBehaviour", + "TestMustRequestIDWithConfig_RequestIDHandler", + "TestMustRequestIDWithConfig_customGenerator", + "TestMustRequestIDWithConfig_skipper", + "TestMustRewriteWithConfig_emptyRulesPanics", + "TestMustRewriteWithConfig_skipper", + "TestMustStaticWithConfig_panicsInvalidDirListTemplate", + "TestNestedJSONUsesFreshDelayedWriter", + "TestNewDefaultFS", + "TestNewHTTPError", + "TestNewRateLimiterMemoryStore", + "TestNewWithConfig", + "TestNonWWWRedirectWithConfig", + "TestParseValue_BindUnmarshaler", + "TestParseValue_Duration", + "TestParseValue_JSONUnmarshaler", + "TestParseValue_OptionsOnlyForTime", + "TestParseValue_TextUnmarshaler", + "TestParseValue_Time", + "TestParseValue_bool", + "TestParseValue_float32", + "TestParseValue_float64", + "TestParseValue_int", + "TestParseValue_int16", + "TestParseValue_int32", + "TestParseValue_int64", + "TestParseValue_int8", + "TestParseValue_string", + "TestParseValue_uint", + "TestParseValue_uint16", + "TestParseValue_uint32", + "TestParseValue_uint64", + "TestParseValue_uint8", + "TestParseValues_bools", + "TestPathParam", + "TestPathParamOr", + "TestPathParam_UnsupportedType", + "TestPathValuesBinder", + "TestPathValuesSizeOverMultipleRequests", + "TestPathValues_Get", + "TestPathValues_GetOr", + "TestPreMiddlewares", + "TestProblemDetailsHTTPErrorHandler", + "TestProblemDetailsHTTPErrorHandler_CommittedResponse", + "TestProblemDetailsHTTPErrorHandler_DoesNotMutateSharedProblem", + "TestProblemError_Error", + "TestProblemError_StatusCode", + "TestProxy", + "TestProxyError", + "TestProxyErrorHandler", + "TestProxyRealIPHeader", + "TestProxyRetries", + "TestProxyRetryWithBackendTimeout", + "TestProxyRewrite", + "TestProxyRewriteRegex", + "TestProxyWebSocketXForwardedFor", + "TestProxyWithConfigWebSocketNonTLS2NonTLS", + "TestProxyWithConfigWebSocketNonTLS2TLS", + "TestProxyWithConfigWebSocketTLS2NonTLS", + "TestProxyWithConfigWebSocketTLS2TLS", + "TestProxyWithNoTargetDoesNotRetry", + "TestProxyWithNoTargetReturnsBadGateway", + "TestQueryParam", + "TestQueryParamOr", + "TestQueryParam_UnsupportedType", + "TestQueryParams", + "TestQueryParamsBinder_FailFast", + "TestQueryParamsOr", + "TestQueryParams_UnsupportedType", + "TestRandomBalancerWithNoTargets", + "TestRandomString", + "TestRandomStringBias", + "TestRandomStringConcurrent", + "TestRateLimiter", + "TestRateLimiterMemoryStore_Allow", + "TestRateLimiterMemoryStore_AllowContextSetsHeaders", + "TestRateLimiterMemoryStore_ConcurrentAccess", + "TestRateLimiterMemoryStore_FractionalRateDefaultBurst", + "TestRateLimiterMemoryStore_RaceDetection", + "TestRateLimiterMemoryStore_TOCTOUFix", + "TestRateLimiterMemoryStore_TimeOrdering", + "TestRateLimiterMemoryStore_cleanupStaleVisitors", + "TestRateLimiterWithConfig", + "TestRateLimiterWithConfig_beforeFunc", + "TestRateLimiterWithConfig_defaultConfig", + "TestRateLimiterWithConfig_defaultDenyHandler", + "TestRateLimiterWithConfig_skipper", + "TestRateLimiterWithConfig_skipperNoSkip", + "TestRateLimiter_storeAllowContextIsPreferred", + "TestRecover", + "TestRecoverErrAbortHandler", + "TestRecoverWithConfig", + "TestRecover_skipper", + "TestRedirectHTTPSNonWWWRedirect", + "TestRedirectHTTPSRedirect", + "TestRedirectHTTPSWWWRedirect", + "TestRedirectNonWWWRedirect", + "TestRedirectWWWRedirect", + "TestRemoveTrailingSlash", + "TestRemoveTrailingSlashWithConfig", + "TestRenderWithTemplateRenderer", + "TestRequestID", + "TestRequestIDConfigDifferentHeader", + "TestRequestIDWithConfig", + "TestRequestID_IDNotAltered", + "TestRequestLoggerError", + "TestRequestLoggerOK", + "TestRequestLoggerWithConfig", + "TestRequestLoggerWithConfig_missingOnLogValuesPanics", + "TestRequestLogger_HandleError", + "TestRequestLogger_ID", + "TestRequestLogger_LogValuesFuncError", + "TestRequestLogger_allFields", + "TestRequestLogger_beforeNextFunc", + "TestRequestLogger_headerIsCaseInsensitive", + "TestRequestLogger_logError", + "TestRequestLogger_skipper", + "TestResolveResponseStatus", + "TestResponse", + "TestResponse_ChangeStatusCodeBeforeWrite", + "TestResponse_Flush", + "TestResponse_FlushPanics", + "TestResponse_Unwrap", + "TestResponse_UnwrapResponse", + "TestResponse_UnwrapResponse_error", + "TestResponse_Write_FallsBackToDefaultStatus", + "TestResponse_Write_UsesSetResponseCode", + "TestResponse_isHijacker", + "TestRewriteAfterRouting", + "TestRewriteURL", + "TestRewriteWithConfigPreMiddleware_Issue1143", + "TestRoundRobinBalancerWithNoTargets", + "TestRouteInfo", + "TestRouteInfo_Reverse", + "TestRouteMultiLevelBacktracking", + "TestRouteMultiLevelBacktracking2", + "TestRoute_ForGroup", + "TestRoute_ToRouteInfo", + "TestRouterAllowHeaderForAnyOtherMethodType", + "TestRouterAnyMatchesLastAddedAnyRoute", + "TestRouterAutoHandleHEADFullHTTPHandlerFlow", + "TestRouterAutoHandleHEAD_204Response", + "TestRouterAutoHandleHEAD_304Response", + "TestRouterAutoHandleHEAD_AnyRoute_NotWrapped", + "TestRouterAutoHandleHEAD_CatchAllRoute", + "TestRouterAutoHandleHEAD_ContentType", + "TestRouterAutoHandleHEAD_CustomResponseHeaders", + "TestRouterAutoHandleHEAD_ExplicitContentLength", + "TestRouterAutoHandleHEAD_HandlerError_ErrorHandlerRuns", + "TestRouterAutoHandleHEAD_MultipleWriteCalls", + "TestRouterAutoHandleHEAD_NoGetRoute_Returns405", + "TestRouterAutoHandleHEAD_PathParams", + "TestRouterAutoHandleHEAD_TransferEncoding", + "TestRouterAutoHandleHEAD_WithMiddleware", + "TestRouterBacktrackingFromMultipleParamKinds", + "TestRouterFillsRequestPatternField", + "TestRouterFindNotPanicOrLoopsWhenContextSetParamValuesIsCalledWithLessValuesThanEchoMaxParam", + "TestRouterGitHubAPI", + "TestRouterHandleMethodOptions", + "TestRouterIssue1348", + "TestRouterMatchAny", + "TestRouterMatchAnyMultiLevel", + "TestRouterMatchAnyMultiLevelWithPost", + "TestRouterMatchAnyPrefixIssue", + "TestRouterMatchAnySlash", + "TestRouterMicroParam", + "TestRouterMixParamMatchAny", + "TestRouterMixedParams", + "TestRouterMultiRoute", + "TestRouterNoRoutablePath", + "TestRouterOptionsMethodHandler", + "TestRouterPanicWhenParamNoRootOnlyChildsFailsFind", + "TestRouterParam", + "TestRouterParam1466", + "TestRouterParamAlias", + "TestRouterParamBacktraceNotFound", + "TestRouterParamNames", + "TestRouterParamOrdering", + "TestRouterParamStaticConflict", + "TestRouterParamWithSlash", + "TestRouterParam_escapeColon", + "TestRouterPriority", + "TestRouterPriorityNotFound", + "TestRouterStatic", + "TestRouterStaticDynamicConflict", + "TestRouterTwoParam", + "TestRouter_Match_DifferentParamNamesForSamePlace", + "TestRouter_ReverseNotFound", + "TestRouter_RouteWhenNotFoundRouteAnyKind", + "TestRouter_RouteWhenNotFoundRouteParamKind", + "TestRouter_RouteWhenNotFoundRouteStaticKind", + "TestRouter_RouteWhenNotFoundRouteWithNodeSplitting", + "TestRouter_Routes", + "TestRouter_addAndMatchAllSupportedMethods", + "TestRouter_addEmptyPathToSlashReverse", + "TestRoutes_Clone", + "TestRoutes_FilterByMethod", + "TestRoutes_FilterByName", + "TestRoutes_FilterByPath", + "TestRoutes_FindByMethodPath", + "TestRoutes_Reverse", + "TestRoutes_ReverseHandlerName", + "TestSecure", + "TestSecureWithConfig", + "TestSecureWithConfig_CSPReportOnly", + "TestSecureWithConfig_HSTSExcludeSubdomains", + "TestSecureWithConfig_HSTSPreloadEnabled", + "TestStartConfig_GracefulShutdown", + "TestStartConfig_Start", + "TestStartConfig_StartTLS", + "TestStartConfig_Start_createListenerError", + "TestStartConfig_WithBeforeServeFunc", + "TestStartConfig_WithHTTP2WithCustomTlsConfig", + "TestStartConfig_WithHideBanner", + "TestStartConfig_WithHidePort", + "TestStartConfig_WithListenerNetwork", + "TestStatic", + "TestStaticDirectoryHandlerAndRouterInconsistentEscaping", + "TestStaticDirectoryHandler_EncodedSeparatorDoesNotBypassRoute", + "TestStaticHTML5PreservesMatchedHandlerNotFound", + "TestStaticMiddlewareAndRouterInconsistentEscaping", + "TestStatic_CustomFS", + "TestStatic_DirectoryBrowsing", + "TestStatic_EncodedSeparatorDoesNotBypassRoute", + "TestStatic_percentEncodedTraversalIsBlocked", + "TestStatic_servesFileWithPercentInName", + "TestStatic_useCaseForApiAndSPAs", + "TestStatusCode", + "TestTargetProvider", + "TestTestRequestLogger", + "TestTimeFormatBinding", + "TestToMultipleFields", + "TestTrustIPRange", + "TestTrustLinkLocal", + "TestTrustLoopback", + "TestTrustPrivateNet", + "TestValidateOrigins", + "TestValueBinder_BindError", + "TestValueBinder_BindUnmarshaler", + "TestValueBinder_BindWithDelimiter", + "TestValueBinder_BindWithDelimiter_types", + "TestValueBinder_Bool", + "TestValueBinder_Bools", + "TestValueBinder_CustomFunc", + "TestValueBinder_CustomFuncWithError", + "TestValueBinder_Duration", + "TestValueBinder_DurationError", + "TestValueBinder_Durations", + "TestValueBinder_DurationsError", + "TestValueBinder_Float32", + "TestValueBinder_Float32s", + "TestValueBinder_Float64", + "TestValueBinder_Float64s", + "TestValueBinder_GetValues", + "TestValueBinder_Int64_intValue", + "TestValueBinder_Int64s_intsValue", + "TestValueBinder_Int_Types", + "TestValueBinder_Int_errorMessage", + "TestValueBinder_Ints_Types", + "TestValueBinder_Ints_Types_FailFast", + "TestValueBinder_JSONUnmarshaler", + "TestValueBinder_MustCustomFunc", + "TestValueBinder_String", + "TestValueBinder_Strings", + "TestValueBinder_TextUnmarshaler", + "TestValueBinder_Time", + "TestValueBinder_TimeError", + "TestValueBinder_Times", + "TestValueBinder_TimesError", + "TestValueBinder_Uint64_uintValue", + "TestValueBinder_Uint64s_uintsValue", + "TestValueBinder_UnixTime", + "TestValueBinder_UnixTimeMilli", + "TestValueBinder_UnixTimeNano", + "TestValueBinder_errorStopsBinding", + "TestValuesFromCookie", + "TestValuesFromForm", + "TestValuesFromHeader", + "TestValuesFromParam", + "TestValuesFromQuery", + "TestVirtualHostHandler", + "TestWrapHeadHandler_HandlerPanic_OriginalWriterRestored", + "TestWrapHeadHandler_PreservesCustomResponseHeaders", + "TestWrapHeadHandler_PropagatesHandlerError", + "TestWrapHeadHandler_RestoresOriginalWriterAfterHandler", + "TestWrapHeadHandler_RouteLevelMiddlewareSeesTrueCommitted", + "TestWrapHeadHandler_SuppressesBodyWrittenByHandler", + "Test_allowOriginFunc", + "Test_allowOriginScheme", + "Test_matchScheme" + ], + "gold_test_outcomes": { + "run": 622, + "passed": 622, + "failed": [] + }, + "validation": { + "gold": { + "resolved": true, + "sites_ok": true, + "green": true, + "n_run": 622 + }, + "empty": { + "resolved": false, + "sites_ok": false, + "missed_sites": 76 + }, + "partial": { + "resolved": false, + "sites_ok": false, + "green": false, + "missed_sites": 2, + "n_run": 411 + } + } +} \ No newline at end of file diff --git a/harness/tasks/e2e/deep__echo__NewHTTPError_add_internal.json b/harness/tasks/e2e/deep__echo__NewHTTPError_add_internal.json new file mode 100644 index 00000000..0e8731cb --- /dev/null +++ b/harness/tasks/e2e/deep__echo__NewHTTPError_add_internal.json @@ -0,0 +1,1375 @@ +{ + "instance_id": "deep__echo__NewHTTPError_add_internal", + "repo": "labstack/echo", + "lang": "go", + "base_commit": "3d084be9022432c5a5257924c7d74bfc3444b456", + "instruction": "`echo.NewHTTPError(code int, message string) *HTTPError` (httperror.go) cannot record the underlying cause; callers chain `.Wrap(err)` afterwards, which allocates a second error. Add a third, required parameter `internal error` so the function becomes `NewHTTPError(code int, message string, internal error) *HTTPError`, storing it as the wrapped error (what `Unwrap` returns). Update every call, in source and in tests: where the result of `NewHTTPError(...)` is immediately wrapped with `.Wrap(x)`, pass `x` as the new argument and drop the `.Wrap` call; everywhere else pass `nil`. Do not change `HTTPError.Wrap` itself, the `HTTPError{...}` literals, or the predefined `Err*` values' use of `.Wrap`. Do not keep a two-argument variant. Behavior must not change.", + "shapes": [ + { + "id": "NewHTTPError/2", + "name": "NewHTTPError", + "arity": 2 + }, + { + "id": "NewHTTPError(...).Wrap", + "regex": "\\bNewHTTPError\\s*\\((?:[^()]|\\((?:[^()]|\\([^()]*\\))*\\))*\\)\\s*\\.Wrap\\(" + } + ], + "source": "seeded", + "site_mode": "shapes", + "gold_tool": "build_deep.py go recipe: every NewHTTPError call (unique name) gets `, nil`, or the argument of an immediately chained .Wrap(x) (which is removed); go build + go test compile clean (go1.25.14 GOTOOLCHAIN=local); gofmt", + "change": "add required parameter (package function; call sites that chain .Wrap(x) must fold x into the new argument)", + "notes": "", + "kind": "wide", + "patch": "diff --git a/echotest/context_test.go b/echotest/context_test.go\nindex 66815e4..d9495d7 100644\n--- a/echotest/context_test.go\n+++ b/echotest/context_test.go\n@@ -26,7 +26,7 @@ func TestServeWithHandler(t *testing.T) {\n \n func TestServeWithHandler_error(t *testing.T) {\n \thandler := func(c *echo.Context) error {\n-\t\treturn echo.NewHTTPError(http.StatusBadRequest, \"something went wrong\")\n+\t\treturn echo.NewHTTPError(http.StatusBadRequest, \"something went wrong\", nil)\n \t}\n \ttestConf := ContextConfig{\n \t\tQueryValues: url.Values{\"key\": []string{\"value\"}},\ndiff --git a/httperror.go b/httperror.go\nindex 8cb10c8..6a464c3 100644\n--- a/httperror.go\n+++ b/httperror.go\n@@ -96,10 +96,11 @@ func ResolveResponseStatus(rw http.ResponseWriter, err error) (resp *Response, s\n }\n \n // NewHTTPError creates a new instance of HTTPError\n-func NewHTTPError(code int, message string) *HTTPError {\n+func NewHTTPError(code int, message string, internal error) *HTTPError {\n \treturn &HTTPError{\n \t\tCode: code,\n \t\tMessage: message,\n+\t\terr: internal,\n \t}\n }\n \ndiff --git a/httperror_test.go b/httperror_test.go\nindex 778a186..32cc8a2 100644\n--- a/httperror_test.go\n+++ b/httperror_test.go\n@@ -62,7 +62,7 @@ func TestHTTPError_WrapUnwrap(t *testing.T) {\n }\n \n func TestNewHTTPError(t *testing.T) {\n-\terr := NewHTTPError(http.StatusBadRequest, \"bad\")\n+\terr := NewHTTPError(http.StatusBadRequest, \"bad\", nil)\n \terr2 := &HTTPError{Code: http.StatusBadRequest, Message: \"bad\"}\n \n \tassert.Equal(t, err2, err)\ndiff --git a/middleware/body_limit.go b/middleware/body_limit.go\nindex 4f1963e..317c6e5 100644\n--- a/middleware/body_limit.go\n+++ b/middleware/body_limit.go\n@@ -69,7 +69,7 @@ func (config BodyLimitConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n \t\t\t// Based on content read\n \t\t\tr, ok := pool.Get().(*limitedReader)\n \t\t\tif !ok {\n-\t\t\t\treturn echo.NewHTTPError(http.StatusInternalServerError, \"invalid pool object\")\n+\t\t\t\treturn echo.NewHTTPError(http.StatusInternalServerError, \"invalid pool object\", nil)\n \t\t\t}\n \t\t\tr.Reset(req.Body)\n \t\t\tdefer pool.Put(r)\ndiff --git a/middleware/compress.go b/middleware/compress.go\nindex 7754d5d..324ba20 100644\n--- a/middleware/compress.go\n+++ b/middleware/compress.go\n@@ -95,7 +95,7 @@ func (config GzipConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n \t\t\t\ti := pool.Get()\n \t\t\t\tw, ok := i.(*gzip.Writer)\n \t\t\t\tif !ok {\n-\t\t\t\t\treturn echo.NewHTTPError(http.StatusInternalServerError, \"invalid pool object\")\n+\t\t\t\t\treturn echo.NewHTTPError(http.StatusInternalServerError, \"invalid pool object\", nil)\n \t\t\t\t}\n \t\t\t\trw := res\n \t\t\t\tw.Reset(rw)\ndiff --git a/middleware/context_timeout_test.go b/middleware/context_timeout_test.go\nindex c7ba76b..5ef9aec 100644\n--- a/middleware/context_timeout_test.go\n+++ b/middleware/context_timeout_test.go\n@@ -69,7 +69,7 @@ func TestContextTimeoutErrorOutInHandler(t *testing.T) {\n \t\t// this error must not be written to the client response. Middlewares upstream of timeout middleware must be able\n \t\t// to handle returned error and this can be done only then handler has not yet committed (written status code)\n \t\t// the response.\n-\t\treturn echo.NewHTTPError(http.StatusTeapot, \"err\")\n+\t\treturn echo.NewHTTPError(http.StatusTeapot, \"err\", nil)\n \t})(c)\n \n \tassert.Error(t, err)\ndiff --git a/middleware/csrf.go b/middleware/csrf.go\nindex 3999a92..ed4d620 100644\n--- a/middleware/csrf.go\n+++ b/middleware/csrf.go\n@@ -305,7 +305,7 @@ func (config CSRFConfig) checkSecFetchSiteRequest(c *echo.Context) (bool, error)\n \t}\n \n \tif secFetchSite == \"same-site\" {\n-\t\treturn false, echo.NewHTTPError(http.StatusForbidden, \"same-site request blocked by CSRF\")\n+\t\treturn false, echo.NewHTTPError(http.StatusForbidden, \"same-site request blocked by CSRF\", nil)\n \t}\n-\treturn false, echo.NewHTTPError(http.StatusForbidden, \"cross-site request blocked by CSRF\")\n+\treturn false, echo.NewHTTPError(http.StatusForbidden, \"cross-site request blocked by CSRF\", nil)\n }\ndiff --git a/middleware/csrf_test.go b/middleware/csrf_test.go\nindex 1a6b18e..107b01c 100644\n--- a/middleware/csrf_test.go\n+++ b/middleware/csrf_test.go\n@@ -513,7 +513,7 @@ func TestCSRFConfig_skipper(t *testing.T) {\n func TestCSRFErrorHandling(t *testing.T) {\n \tcfg := CSRFConfig{\n \t\tErrorHandler: func(c *echo.Context, err error) error {\n-\t\t\treturn echo.NewHTTPError(http.StatusTeapot, \"error_handler_executed\")\n+\t\t\treturn echo.NewHTTPError(http.StatusTeapot, \"error_handler_executed\", nil)\n \t\t},\n \t}\n \n@@ -801,7 +801,7 @@ func TestCSRFConfig_checkSecFetchSiteRequest(t *testing.T) {\n \t\t\tname: \"nok, unsafe POST + same-site + custom func returns custom error\",\n \t\t\tgivenConfig: CSRFConfig{\n \t\t\t\tAllowSecFetchSiteFunc: func(c *echo.Context) (bool, error) {\n-\t\t\t\t\treturn false, echo.NewHTTPError(http.StatusTeapot, \"custom error from func\")\n+\t\t\t\t\treturn false, echo.NewHTTPError(http.StatusTeapot, \"custom error from func\", nil)\n \t\t\t\t},\n \t\t\t},\n \t\t\twhenMethod: http.MethodPost,\n@@ -834,7 +834,7 @@ func TestCSRFConfig_checkSecFetchSiteRequest(t *testing.T) {\n \t\t\tgivenConfig: CSRFConfig{\n \t\t\t\tTrustedOrigins: []string{\"https://trusted.example.com\"},\n \t\t\t\tAllowSecFetchSiteFunc: func(c *echo.Context) (bool, error) {\n-\t\t\t\t\treturn false, echo.NewHTTPError(http.StatusTeapot, \"should not be called\")\n+\t\t\t\t\treturn false, echo.NewHTTPError(http.StatusTeapot, \"should not be called\", nil)\n \t\t\t\t},\n \t\t\t},\n \t\t\twhenMethod: http.MethodPost,\n@@ -847,7 +847,7 @@ func TestCSRFConfig_checkSecFetchSiteRequest(t *testing.T) {\n \t\t\tgivenConfig: CSRFConfig{\n \t\t\t\tTrustedOrigins: []string{\"https://trusted.example.com\"},\n \t\t\t\tAllowSecFetchSiteFunc: func(c *echo.Context) (bool, error) {\n-\t\t\t\t\treturn false, echo.NewHTTPError(http.StatusTeapot, \"custom block\")\n+\t\t\t\t\treturn false, echo.NewHTTPError(http.StatusTeapot, \"custom block\", nil)\n \t\t\t\t},\n \t\t\t},\n \t\t\twhenMethod: http.MethodPost,\ndiff --git a/middleware/decompress.go b/middleware/decompress.go\nindex 52febc6..479f74c 100644\n--- a/middleware/decompress.go\n+++ b/middleware/decompress.go\n@@ -91,9 +91,9 @@ func (config DecompressConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n \t\t\tgr, ok := i.(*gzip.Reader)\n \t\t\tif !ok || gr == nil {\n \t\t\t\tif err, isErr := i.(error); isErr {\n-\t\t\t\t\treturn echo.NewHTTPError(http.StatusInternalServerError, err.Error())\n+\t\t\t\t\treturn echo.NewHTTPError(http.StatusInternalServerError, err.Error(), nil)\n \t\t\t\t}\n-\t\t\t\treturn echo.NewHTTPError(http.StatusInternalServerError, \"unexpected type from gzip decompression pool\")\n+\t\t\t\treturn echo.NewHTTPError(http.StatusInternalServerError, \"unexpected type from gzip decompression pool\", nil)\n \t\t\t}\n \t\t\tdefer pool.Put(gr)\n \n@@ -128,7 +128,6 @@ func (config DecompressConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n \t}, nil\n }\n \n-\n // isGzipContentEncoding reports whether Content-Encoding is gzip.\n // Content codings are case-insensitive per RFC 9110 \u00a78.4.1.\n func isGzipContentEncoding(v string) bool {\ndiff --git a/middleware/key_auth.go b/middleware/key_auth.go\nindex 2dcb980..2ad8d3e 100644\n--- a/middleware/key_auth.go\n+++ b/middleware/key_auth.go\n@@ -103,10 +103,10 @@ type KeyAuthValidator func(c *echo.Context, key string, source ExtractorSource)\n type KeyAuthErrorHandler func(c *echo.Context, err error) error\n \n // ErrKeyMissing denotes an error raised when key value could not be extracted from request\n-var ErrKeyMissing = echo.NewHTTPError(http.StatusUnauthorized, \"missing key\")\n+var ErrKeyMissing = echo.NewHTTPError(http.StatusUnauthorized, \"missing key\", nil)\n \n // ErrInvalidKey denotes an error raised when key value is invalid by validator\n-var ErrInvalidKey = echo.NewHTTPError(http.StatusUnauthorized, \"invalid key\")\n+var ErrInvalidKey = echo.NewHTTPError(http.StatusUnauthorized, \"invalid key\", nil)\n \n // DefaultKeyAuthConfig is the default KeyAuth middleware config.\n var DefaultKeyAuthConfig = KeyAuthConfig{\ndiff --git a/middleware/key_auth_test.go b/middleware/key_auth_test.go\nindex 49a917e..6d49f69 100644\n--- a/middleware/key_auth_test.go\n+++ b/middleware/key_auth_test.go\n@@ -193,7 +193,7 @@ func TestKeyAuthWithConfig(t *testing.T) {\n \t\t\twhenConfig: func(conf *KeyAuthConfig) {\n \t\t\t\tconf.KeyLookup = \"header:token\"\n \t\t\t\tconf.ErrorHandler = func(c *echo.Context, err error) error {\n-\t\t\t\t\treturn echo.NewHTTPError(http.StatusTeapot, \"custom\").Wrap(err)\n+\t\t\t\t\treturn echo.NewHTTPError(http.StatusTeapot, \"custom\", err)\n \t\t\t\t}\n \t\t\t},\n \t\t\texpectHandlerCalled: false,\n@@ -206,7 +206,7 @@ func TestKeyAuthWithConfig(t *testing.T) {\n \t\t\t},\n \t\t\twhenConfig: func(conf *KeyAuthConfig) {\n \t\t\t\tconf.ErrorHandler = func(c *echo.Context, err error) error {\n-\t\t\t\t\treturn echo.NewHTTPError(http.StatusTeapot, \"custom\").Wrap(err)\n+\t\t\t\t\treturn echo.NewHTTPError(http.StatusTeapot, \"custom\", err)\n \t\t\t\t}\n \t\t\t},\n \t\t\texpectHandlerCalled: false,\ndiff --git a/middleware/proxy.go b/middleware/proxy.go\nindex 497aefe..c5e3952 100644\n--- a/middleware/proxy.go\n+++ b/middleware/proxy.go\n@@ -152,7 +152,7 @@ func proxyRaw(c *echo.Context, t *ProxyTarget, config ProxyConfig) http.Handler\n \n \t\tout, err := dialFunc(c.Request().Context(), \"tcp\", t.URL.Host)\n \t\tif err != nil {\n-\t\t\tc.Set(\"_error\", echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf(\"proxy raw, dial error=%v, url=%s\", err, t.URL)))\n+\t\t\tc.Set(\"_error\", echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf(\"proxy raw, dial error=%v, url=%s\", err, t.URL), nil))\n \t\t\treturn\n \t\t}\n \t\tdefer out.Close()\n@@ -160,7 +160,7 @@ func proxyRaw(c *echo.Context, t *ProxyTarget, config ProxyConfig) http.Handler\n \t\t// Write header\n \t\terr = r.Write(out)\n \t\tif err != nil {\n-\t\t\tc.Set(\"_error\", echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf(\"proxy raw, request header copy error=%v, url=%s\", err, t.URL)))\n+\t\t\tc.Set(\"_error\", echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf(\"proxy raw, request header copy error=%v, url=%s\", err, t.URL), nil))\n \t\t\treturn\n \t\t}\n \n@@ -372,7 +372,7 @@ func (config ProxyConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n \t\t\t\t\treturn config.ErrorHandler(c, err)\n \t\t\t\t}\n \t\t\t\tif tgt == nil || tgt.URL == nil {\n-\t\t\t\t\treturn config.ErrorHandler(c, echo.NewHTTPError(http.StatusBadGateway, \"no proxy target available\"))\n+\t\t\t\t\treturn config.ErrorHandler(c, echo.NewHTTPError(http.StatusBadGateway, \"no proxy target available\", nil))\n \t\t\t\t}\n \n \t\t\t\tc.Set(config.ContextKey, tgt)\n@@ -433,13 +433,12 @@ func proxyHTTP(c *echo.Context, tgt *ProxyTarget, config ProxyConfig) http.Handl\n \t\t// https://github.com/golang/go/blob/6965b01ea248cabb70c3749fd218b36089a21efb/src/net/net.go#L416-L430\n \t\t// From Caddy https://github.com/caddyserver/caddy/blob/afa778ae05503f563af0d1015cdf7e5e78b1eeec/modules/caddyhttp/reverseproxy/reverseproxy.go#L1352\n \t\tif errors.Is(err, context.Canceled) || strings.Contains(err.Error(), \"operation was canceled\") {\n-\t\t\thttpError := echo.NewHTTPError(StatusCodeContextCanceled, \"client closed connection\").Wrap(err)\n+\t\t\thttpError := echo.NewHTTPError(StatusCodeContextCanceled, \"client closed connection\", err)\n \t\t\tc.Set(\"_error\", httpError)\n \t\t} else {\n \t\t\thttpError := echo.NewHTTPError(\n \t\t\t\thttp.StatusBadGateway,\n-\t\t\t\t\"remote server unreachable, could not proxy request\",\n-\t\t\t).Wrap(fmt.Errorf(\"server: %s, err: %w\", desc, err))\n+\t\t\t\t\"remote server unreachable, could not proxy request\", fmt.Errorf(\"server: %s, err: %w\", desc, err))\n \t\t\tc.Set(\"_error\", httpError)\n \t\t}\n \t}\ndiff --git a/middleware/proxy_test.go b/middleware/proxy_test.go\nindex 5053f79..3666da9 100644\n--- a/middleware/proxy_test.go\n+++ b/middleware/proxy_test.go\n@@ -422,7 +422,7 @@ func TestFailNextTarget(t *testing.T) {\n \te := echo.New()\n \ttp := &testProvider{}\n \ttp.target = &ProxyTarget{Name: \"target 1\", URL: url1}\n-\ttp.err = echo.NewHTTPError(http.StatusInternalServerError, \"method could not select target\")\n+\ttp.err = echo.NewHTTPError(http.StatusInternalServerError, \"method could not select target\", nil)\n \n \te.Use(Proxy(tp))\n \trec := httptest.NewRecorder()\ndiff --git a/middleware/rate_limiter.go b/middleware/rate_limiter.go\nindex bd70e10..0b2bd40 100644\n--- a/middleware/rate_limiter.go\n+++ b/middleware/rate_limiter.go\n@@ -52,10 +52,10 @@ type RateLimiterConfig struct {\n type Extractor func(c *echo.Context) (string, error)\n \n // ErrRateLimitExceeded denotes an error raised when rate limit is exceeded\n-var ErrRateLimitExceeded = echo.NewHTTPError(http.StatusTooManyRequests, \"rate limit exceeded\")\n+var ErrRateLimitExceeded = echo.NewHTTPError(http.StatusTooManyRequests, \"rate limit exceeded\", nil)\n \n // ErrExtractorError denotes an error raised when extractor function is unsuccessful\n-var ErrExtractorError = echo.NewHTTPError(http.StatusForbidden, \"error while extracting identifier\")\n+var ErrExtractorError = echo.NewHTTPError(http.StatusForbidden, \"error while extracting identifier\", nil)\n \n // DefaultRateLimiterConfig defines default values for RateLimiterConfig\n var DefaultRateLimiterConfig = RateLimiterConfig{\ndiff --git a/middleware/request_logger_test.go b/middleware/request_logger_test.go\nindex 2232c6f..a4be28e 100644\n--- a/middleware/request_logger_test.go\n+++ b/middleware/request_logger_test.go\n@@ -214,7 +214,7 @@ func TestRequestLogger_logError(t *testing.T) {\n \t}))\n \n \te.GET(\"/test\", func(c *echo.Context) error {\n-\t\treturn echo.NewHTTPError(http.StatusNotAcceptable, \"nope\")\n+\t\treturn echo.NewHTTPError(http.StatusNotAcceptable, \"nope\", nil)\n \t})\n \n \treq := httptest.NewRequest(http.MethodGet, \"/test\", nil)\n@@ -252,7 +252,7 @@ func TestRequestLogger_HandleError(t *testing.T) {\n \t}\n \n \te.GET(\"/test\", func(c *echo.Context) error {\n-\t\treturn echo.NewHTTPError(http.StatusForbidden, \"nope\")\n+\t\treturn echo.NewHTTPError(http.StatusForbidden, \"nope\", nil)\n \t})\n \n \treq := httptest.NewRequest(http.MethodGet, \"/test\", nil)\n@@ -265,7 +265,7 @@ func TestRequestLogger_HandleError(t *testing.T) {\n \texpect := RequestLoggerValues{\n \t\tStartTime: time.Unix(1631045377, 0).UTC(),\n \t\tStatus: http.StatusTeapot,\n-\t\tError: echo.NewHTTPError(http.StatusForbidden, \"nope\"),\n+\t\tError: echo.NewHTTPError(http.StatusForbidden, \"nope\", nil),\n \t}\n \tassert.Equal(t, expect, actual)\n }\n@@ -278,7 +278,7 @@ func TestRequestLogger_LogValuesFuncError(t *testing.T) {\n \t\tLogStatus: true,\n \t\tLogValuesFunc: func(c *echo.Context, values RequestLoggerValues) error {\n \t\t\texpect = values\n-\t\t\treturn echo.NewHTTPError(http.StatusNotAcceptable, \"LogValuesFuncError\")\n+\t\t\treturn echo.NewHTTPError(http.StatusNotAcceptable, \"LogValuesFuncError\", nil)\n \t\t},\n \t}))\n \n@@ -481,7 +481,7 @@ func TestTestRequestLogger(t *testing.T) {\n \t\t},\n \t\t{\n \t\t\tname: \"error\",\n-\t\t\twhenError: echo.NewHTTPError(http.StatusBadGateway, \"bad gw\"),\n+\t\t\twhenError: echo.NewHTTPError(http.StatusBadGateway, \"bad gw\", nil),\n \t\t\texpectStatus: \"502\",\n \t\t\texpectError: `\"error\":\"code=502, message=bad gw\"`,\n \t\t},\ndiff --git a/middleware/static_test.go b/middleware/static_test.go\nindex 889169e..f3cd72b 100644\n--- a/middleware/static_test.go\n+++ b/middleware/static_test.go\n@@ -62,7 +62,7 @@ func TestStaticHTML5PreservesMatchedHandlerNotFound(t *testing.T) {\n \t\t\t\t\tHTML5: true,\n \t\t\t\t}))\n \t\t\t\te.GET(\"/api/users/:id\", func(c *echo.Context) error {\n-\t\t\t\t\treturn echo.NewHTTPError(http.StatusNotFound, \"user not found\")\n+\t\t\t\t\treturn echo.NewHTTPError(http.StatusNotFound, \"user not found\", nil)\n \t\t\t\t})\n \t\t\t\treturn e\n \t\t\t},\n", + "test_patch": "", + "fail_to_pass": [], + "problem_statement": "`echo.NewHTTPError(code int, message string) *HTTPError` (httperror.go) cannot record the underlying cause; callers chain `.Wrap(err)` afterwards, which allocates a second error. Add a third, required parameter `internal error` so the function becomes `NewHTTPError(code int, message string, internal error) *HTTPError`, storing it as the wrapped error (what `Unwrap` returns). Update every call, in source and in tests: where the result of `NewHTTPError(...)` is immediately wrapped with `.Wrap(x)`, pass `x` as the new argument and drop the `.Wrap` call; everywhere else pass `nil`. Do not change `HTTPError.Wrap` itself, the `HTTPError{...}` literals, or the predefined `Err*` values' use of `.Wrap`. Do not keep a two-argument variant. Behavior must not change.", + "prompt_source": "wide-mandate", + "gold_files": [ + "echotest/context_test.go", + "httperror.go", + "httperror_test.go", + "middleware/body_limit.go", + "middleware/compress.go", + "middleware/context_timeout_test.go", + "middleware/csrf.go", + "middleware/csrf_test.go", + "middleware/decompress.go", + "middleware/key_auth.go", + "middleware/key_auth_test.go", + "middleware/proxy.go", + "middleware/proxy_test.go", + "middleware/rate_limiter.go", + "middleware/request_logger_test.go", + "middleware/static_test.go" + ], + "base_shape_counts": { + "NewHTTPError/2": { + "echotest/context_test.go": 1, + "httperror.go": 1, + "httperror_test.go": 1, + "middleware/body_limit.go": 1, + "middleware/compress.go": 1, + "middleware/context_timeout_test.go": 1, + "middleware/csrf.go": 2, + "middleware/csrf_test.go": 4, + "middleware/decompress.go": 2, + "middleware/key_auth.go": 2, + "middleware/key_auth_test.go": 2, + "middleware/proxy.go": 5, + "middleware/proxy_test.go": 1, + "middleware/rate_limiter.go": 2, + "middleware/request_logger_test.go": 5, + "middleware/static_test.go": 1 + }, + "NewHTTPError(...).Wrap": { + "middleware/key_auth_test.go": 2, + "middleware/proxy.go": 2 + } + }, + "gold_shape_counts": { + "NewHTTPError/2": {}, + "NewHTTPError(...).Wrap": {} + }, + "gold_sites": 36, + "gold_site_files": 16, + "test_functions": [ + "TestAddTrailingSlash", + "TestAddTrailingSlashWithConfig", + "TestAutoHeadExplicitHeadTakesPrecedence", + "TestBasicAuth", + "TestBasicAuthRealm", + "TestBasicAuthWithConfig_panic", + "TestBasicAuth_panic", + "TestBindCachedMetaPreservesFieldNameError", + "TestBindForm", + "TestBindHeaderParam", + "TestBindHeaderParamBadType", + "TestBindInt8", + "TestBindJSON", + "TestBindMultipartForm", + "TestBindMultipartFormFiles", + "TestBindParam", + "TestBindQueryParams", + "TestBindQueryParamsCaseInsensitive", + "TestBindQueryParamsCaseSensitivePrioritized", + "TestBindSetWithProperType", + "TestBindUnmarshalParam", + "TestBindUnmarshalParamAnonymousFieldPtr", + "TestBindUnmarshalParamAnonymousFieldPtrCustomTag", + "TestBindUnmarshalParamAnonymousFieldPtrNil", + "TestBindUnmarshalParamExtras", + "TestBindUnmarshalParamPtr", + "TestBindUnmarshalParams", + "TestBindUnmarshalText", + "TestBindUnmarshalTextPtr", + "TestBindUnmarshalTypeError", + "TestBindUnsupportedMediaType", + "TestBindWithDelimiter_invalidType", + "TestBindXML", + "TestBind_formConversionErrorIncludesFieldName", + "TestBindbindData", + "TestBindingError_Error", + "TestBindingError_ErrorJSON", + "TestBindingError_marshalJSON_emptyMessageFallsBackToStatusText", + "TestBindingError_serializesToStructuredJSON", + "TestBodyDump", + "TestBodyDumpResponseWriter_CanFlush", + "TestBodyDumpResponseWriter_CanHijack", + "TestBodyDumpResponseWriter_CanNotFlush", + "TestBodyDumpResponseWriter_CanNotHijack", + "TestBodyDumpResponseWriter_CanUnwrap", + "TestBodyDumpWithConfig_panic", + "TestBodyDump_BothLimitsSimultaneous", + "TestBodyDump_ClientGetsFullResponse", + "TestBodyDump_DefaultConfig", + "TestBodyDump_LargeRequestDosPrevention", + "TestBodyDump_LargeResponseDosPrevention", + "TestBodyDump_ReadError", + "TestBodyDump_RequestAtExactLimit", + "TestBodyDump_RequestExceedsLimit", + "TestBodyDump_RequestWithinLimit", + "TestBodyDump_ResponseExceedsLimit", + "TestBodyDump_ResponseWithinLimit", + "TestBodyDump_fails", + "TestBodyDump_panic", + "TestBodyDump_skipper", + "TestBodyLimit", + "TestBodyLimitAfterDecompressUsesDecodedSize", + "TestBodyLimitConfig_ToMiddleware", + "TestBodyLimitReader", + "TestBodyLimitWithConfig", + "TestBodyLimit_skipper", + "TestCORS", + "TestCORSConfig", + "TestCORSWithConfig_AllowMethods", + "TestCORS_NonPreflightOPTIONSPassThrough", + "TestCSRF", + "TestCSRFConfig_checkSecFetchSiteRequest", + "TestCSRFConfig_skipper", + "TestCSRFErrorHandling", + "TestCSRFSetSameSiteMode", + "TestCSRFWithConfig", + "TestCSRFWithSameSiteDefaultMode", + "TestCSRFWithSameSiteModeNone", + "TestCSRFWithoutSameSiteMode", + "TestCSRF_tokenExtractors", + "TestClientCancelConnectionResultsHTTPCode499", + "TestCompressRequestWithoutDecompressMiddleware", + "TestConcurrentRouter_ConcurrentReadWrite", + "TestConcurrentRouter_ConcurrentReads", + "TestConcurrentRouter_ConcurrentWrites", + "TestConcurrentRouter_ParametersNoRace", + "TestConcurrentRouter_Remove", + "TestConcurrentRouter_RoutesIterationDuringModification", + "TestContextAttachment", + "TestContextCookie", + "TestContextEcho", + "TestContextFormFile", + "TestContextFormValue", + "TestContextGet", + "TestContextGetAndSetPathValuesMutability", + "TestContextGetInvalidCast", + "TestContextGetNonExistentKey", + "TestContextGetOK", + "TestContextGetOrInvalidCast", + "TestContextGetOrNonExistentKey", + "TestContextGetOrOK", + "TestContextHTML", + "TestContextHTMLBlob", + "TestContextInline", + "TestContextJSON", + "TestContextJSONBlob", + "TestContextJSONErrorsOut", + "TestContextJSONP", + "TestContextJSONPBlob", + "TestContextJSONPretty", + "TestContextJSONStatusAcrossReset", + "TestContextJSONWithEmptyIntent", + "TestContextJSONWithNotEchoResponse", + "TestContextMultipartForm", + "TestContextNoContent", + "TestContextRedirect", + "TestContextRenderErrorsOnNoRenderer", + "TestContextRenderTemplate", + "TestContextRenderTemplateError", + "TestContextRequest", + "TestContextResetClearsStore", + "TestContextResponse", + "TestContextStream", + "TestContextTimeoutCanHandleContextDeadlineOnNextHandler", + "TestContextTimeoutErrorOutInHandler", + "TestContextTimeoutSkipper", + "TestContextTimeoutSuccessfulRequest", + "TestContextTimeoutTestRequestClone", + "TestContextTimeoutWithDefaultErrorMessage", + "TestContextTimeoutWithTimeout0", + "TestContextXML", + "TestContextXMLBlob", + "TestContextXMLPretty", + "TestContextXMLWithEmptyIntent", + "TestContext_Bind", + "TestContext_File", + "TestContext_FileFS", + "TestContext_IsWebSocket", + "TestContext_JSON_CommitsCustomResponseCode", + "TestContext_PathParam", + "TestContext_PathParamDefault", + "TestContext_PathValues", + "TestContext_QueryParam", + "TestContext_QueryParamDefault", + "TestContext_QueryParams", + "TestContext_QueryString", + "TestContext_RealIP", + "TestContext_Request", + "TestContext_Scheme", + "TestContext_SetParamNamesShouldNotModifyPathValuesCapacity", + "TestContext_Validate", + "TestCorsHeaders", + "TestCreateExtractors", + "TestDecompress", + "TestDecompressContentEncodingCaseInsensitive", + "TestDecompressErrorReturned", + "TestDecompressNoContent", + "TestDecompressPoolError", + "TestDecompressSkipper", + "TestDecompressWithConfig_DefaultConfig", + "TestDecompressWithConfig_DefaultConfig_noDecode", + "TestDecompress_AtExactLimit", + "TestDecompress_DefaultLimit", + "TestDecompress_ExceedsLimit", + "TestDecompress_LargePayloadDosPrevention", + "TestDecompress_MultipleReads", + "TestDecompress_SmallCustomLimit", + "TestDecompress_UnlimitedExplicit", + "TestDecompress_WithinLimit", + "TestDecompress_ZipBomb", + "TestDecompress_skippedIfNoHeader", + "TestDefaultBinder_BindBody", + "TestDefaultBinder_BindToStructFromMixedSources", + "TestDefaultBinder_bindDataToMap", + "TestDefaultHTTPErrorHandler", + "TestDefaultHTTPErrorHandler_CommitedResponse", + "TestDefaultJSONCodec_Decode", + "TestDefaultJSONCodec_Decode_BodyReadError", + "TestDefaultJSONCodec_Decode_LargeBodyThenNormal", + "TestDefaultJSONCodec_Decode_PooledBufferConcurrent", + "TestDefaultJSONCodec_Decode_PooledBufferReuse", + "TestDefaultJSONCodec_Decode_RejectsTrailingData", + "TestDefaultJSONCodec_Encode", + "TestDefaultRouter_AddDuplicateRouteAllowed", + "TestDefaultRouter_AddDuplicateRouteNotAllowed", + "TestDefaultRouter_AddWithoutHandler", + "TestDefaultRouter_MethodNotAllowedHandler", + "TestDefaultRouter_NotFoundHandler", + "TestDefaultRouter_OptionsMethodHandler", + "TestDefaultRouter_PathValuesCanMatchEmptyValues", + "TestDefaultRouter_Remove", + "TestDefaultRouter_UnescapePathParamValues", + "TestDefaultRouter_UseEscapedPathForRouting", + "TestEcho", + "TestEchoConnect", + "TestEchoContext", + "TestEchoDelete", + "TestEchoFile", + "TestEchoGet", + "TestEchoGroup", + "TestEchoHandler", + "TestEchoHead", + "TestEchoMatch", + "TestEchoMethodNotAllowed", + "TestEchoMiddleware", + "TestEchoMiddlewareError", + "TestEchoNotFound", + "TestEchoOptions", + "TestEchoPatch", + "TestEchoPost", + "TestEchoPut", + "TestEchoQuery", + "TestEchoRewritePreMiddleware", + "TestEchoRewriteReplacementEscaping", + "TestEchoRewriteWithCaret", + "TestEchoRewriteWithRegexRules", + "TestEchoServeHTTPPathEncoding", + "TestEchoStaticRedirectIndex", + "TestEchoTrace", + "TestEchoWrapHandler", + "TestEchoWrapMiddleware", + "TestEcho_Any", + "TestEcho_Any_hasLowerPriority", + "TestEcho_Any_matchesArbitraryMethod", + "TestEcho_FileFS", + "TestEcho_OnAddRoute", + "TestEcho_RouteNotFound", + "TestEcho_Start", + "TestEcho_StaticFS", + "TestEcho_StaticPanic", + "TestExtractIPDirect", + "TestExtractIPFromRealIPHeader", + "TestExtractIPFromXFFHeader", + "TestFailNextTarget", + "TestFilepathOrContent", + "TestFormFieldBinder", + "TestFormValue", + "TestFormValueOr", + "TestFormValue_UnsupportedType", + "TestFormValues", + "TestFormValuesOr", + "TestFormValues_UnsupportedType", + "TestFormat", + "TestGetRawQueryParamMatchesStdlib", + "TestGlobalMiddlewareRunsOnNotFoundAndMethodNotAllowed", + "TestGroupFile", + "TestGroupRouteMiddleware", + "TestGroupRouteMiddlewareWithMatchAny", + "TestGroupRoute_automaticOPTIONS", + "TestGroupRoute_catchAllMasksMethodHandling", + "TestGroupRoute_concreteRoutesResolve", + "TestGroupRoute_methodMismatchReturns405", + "TestGroupStaticFS_EncodedSeparatorDoesNotBypassRoute", + "TestGroup_Any", + "TestGroup_CONNECT", + "TestGroup_DELETE", + "TestGroup_FileFS", + "TestGroup_HEAD", + "TestGroup_Match", + "TestGroup_MatchWithErrors", + "TestGroup_OPTIONS", + "TestGroup_PATCH", + "TestGroup_POST", + "TestGroup_PUT", + "TestGroup_QUERY", + "TestGroup_RouteNotFound", + "TestGroup_RouteNotFoundUsesRouterConfig", + "TestGroup_RouteNotFoundWithMiddleware", + "TestGroup_Static", + "TestGroup_StaticMultiTest", + "TestGroup_StaticPanic", + "TestGroup_TRACE", + "TestGroup_UseMultipleTimes", + "TestGroup_doesNotAffectRootRoutes", + "TestGroup_multiLevelGroup", + "TestGroup_withRoutesWillExecuteMiddlewareFor404", + "TestGroup_withoutRouteWillExecuteMiddleware", + "TestGroup_withoutRouteWillNotExecuteMiddleware", + "TestGzipResponseWriter_CanHijack", + "TestGzipResponseWriter_CanNotHijack", + "TestGzipResponseWriter_CanUnwrap", + "TestGzipWithConfig_invalidLevel", + "TestGzipWithMinLength", + "TestGzipWithMinLengthChunked", + "TestGzipWithMinLengthNoContent", + "TestGzipWithMinLengthTooShort", + "TestGzipWithResponseWithoutBody", + "TestGzipWithStatic", + "TestGzip_AcceptEncodingHeader", + "TestGzip_Empty", + "TestGzip_ErrorReturned", + "TestGzip_NoAcceptEncodingHeader", + "TestGzip_NoContent", + "TestGzip_chunked", + "TestHTTPError_Error", + "TestHTTPError_StatusCode", + "TestHTTPError_WrapUnwrap", + "TestHandlerName", + "TestHeadResponseWriter_Commit_NoContentLength_1xx", + "TestHeadResponseWriter_Commit_NoContentLength_204", + "TestHeadResponseWriter_Commit_NoContentLength_304", + "TestHeadResponseWriter_Commit_NoContentLength_TransferEncoding", + "TestHeadResponseWriter_Commit_NoWriteHeader_WhenNotCommitted", + "TestHeadResponseWriter_Commit_PreservesExplicitContentLength", + "TestHeadResponseWriter_Commit_SetsContentLength", + "TestHeadResponseWriter_Flush_IsNoop", + "TestHeadResponseWriter_Header_DelegatesToUnderlying", + "TestHeadResponseWriter_Hijack_DelegatesToUnderlying", + "TestHeadResponseWriter_Unwrap_ReturnsUnderlying", + "TestHeadResponseWriter_WriteHeader_FirstCallWins", + "TestHeadResponseWriter_WriteHeader_SetsCommittedOnUnderlying", + "TestHeadResponseWriter_Write_CountsBytes", + "TestHeadResponseWriter_Write_ImpliesStatus200", + "TestHeadResponseWriter_Write_MultipleCallsSumBytes", + "TestIPChecker_TrustOption", + "TestIsCORSPreflight", + "TestKeyAuth", + "TestKeyAuthWithConfig", + "TestKeyAuthWithConfig_errors", + "TestKeyAuth_errorHandlerSwallowsError", + "TestLegacyIPExtractor", + "TestLoadBytesOK", + "TestLoadBytesOK_TrimNewlineEnd", + "TestLoadBytes_custom", + "TestLogger", + "TestMethodNotAllowedAndNotFound", + "TestMethodOverride", + "TestMethodOverride_formParam", + "TestMethodOverride_ignoreGet", + "TestMethodOverride_queryParam", + "TestMiddlewares", + "TestModifyResponseUseContext", + "TestMustGzipWithConfig_panics", + "TestMustKeyAuthWithConfig_panic", + "TestMustProxyWithConfig_emptyBalancerPanics", + "TestMustRateLimiterWithConfig_panicBehaviour", + "TestMustRequestIDWithConfig_RequestIDHandler", + "TestMustRequestIDWithConfig_customGenerator", + "TestMustRequestIDWithConfig_skipper", + "TestMustRewriteWithConfig_emptyRulesPanics", + "TestMustRewriteWithConfig_skipper", + "TestMustStaticWithConfig_panicsInvalidDirListTemplate", + "TestNestedJSONUsesFreshDelayedWriter", + "TestNewDefaultFS", + "TestNewHTTPError", + "TestNewRateLimiterMemoryStore", + "TestNewWithConfig", + "TestNonWWWRedirectWithConfig", + "TestParseValue_BindUnmarshaler", + "TestParseValue_Duration", + "TestParseValue_JSONUnmarshaler", + "TestParseValue_OptionsOnlyForTime", + "TestParseValue_TextUnmarshaler", + "TestParseValue_Time", + "TestParseValue_bool", + "TestParseValue_float32", + "TestParseValue_float64", + "TestParseValue_int", + "TestParseValue_int16", + "TestParseValue_int32", + "TestParseValue_int64", + "TestParseValue_int8", + "TestParseValue_string", + "TestParseValue_uint", + "TestParseValue_uint16", + "TestParseValue_uint32", + "TestParseValue_uint64", + "TestParseValue_uint8", + "TestParseValues_bools", + "TestPathParam", + "TestPathParamOr", + "TestPathParam_UnsupportedType", + "TestPathValuesBinder", + "TestPathValuesSizeOverMultipleRequests", + "TestPathValues_Get", + "TestPathValues_GetOr", + "TestPreMiddlewares", + "TestProblemDetailsHTTPErrorHandler", + "TestProblemDetailsHTTPErrorHandler_CommittedResponse", + "TestProblemDetailsHTTPErrorHandler_DoesNotMutateSharedProblem", + "TestProblemError_Error", + "TestProblemError_StatusCode", + "TestProxy", + "TestProxyError", + "TestProxyErrorHandler", + "TestProxyRealIPHeader", + "TestProxyRetries", + "TestProxyRetryWithBackendTimeout", + "TestProxyRewrite", + "TestProxyRewriteRegex", + "TestProxyWebSocketXForwardedFor", + "TestProxyWithConfigWebSocketNonTLS2NonTLS", + "TestProxyWithConfigWebSocketNonTLS2TLS", + "TestProxyWithConfigWebSocketTLS2NonTLS", + "TestProxyWithConfigWebSocketTLS2TLS", + "TestProxyWithNoTargetDoesNotRetry", + "TestProxyWithNoTargetReturnsBadGateway", + "TestQueryParam", + "TestQueryParamOr", + "TestQueryParam_UnsupportedType", + "TestQueryParams", + "TestQueryParamsBinder_FailFast", + "TestQueryParamsOr", + "TestQueryParams_UnsupportedType", + "TestRandomBalancerWithNoTargets", + "TestRandomString", + "TestRandomStringBias", + "TestRandomStringConcurrent", + "TestRateLimiter", + "TestRateLimiterMemoryStore_Allow", + "TestRateLimiterMemoryStore_AllowContextSetsHeaders", + "TestRateLimiterMemoryStore_ConcurrentAccess", + "TestRateLimiterMemoryStore_FractionalRateDefaultBurst", + "TestRateLimiterMemoryStore_RaceDetection", + "TestRateLimiterMemoryStore_TOCTOUFix", + "TestRateLimiterMemoryStore_TimeOrdering", + "TestRateLimiterMemoryStore_cleanupStaleVisitors", + "TestRateLimiterWithConfig", + "TestRateLimiterWithConfig_beforeFunc", + "TestRateLimiterWithConfig_defaultConfig", + "TestRateLimiterWithConfig_defaultDenyHandler", + "TestRateLimiterWithConfig_skipper", + "TestRateLimiterWithConfig_skipperNoSkip", + "TestRateLimiter_storeAllowContextIsPreferred", + "TestRecover", + "TestRecoverErrAbortHandler", + "TestRecoverWithConfig", + "TestRecover_skipper", + "TestRedirectHTTPSNonWWWRedirect", + "TestRedirectHTTPSRedirect", + "TestRedirectHTTPSWWWRedirect", + "TestRedirectNonWWWRedirect", + "TestRedirectWWWRedirect", + "TestRemoveTrailingSlash", + "TestRemoveTrailingSlashWithConfig", + "TestRenderWithTemplateRenderer", + "TestRequestID", + "TestRequestIDConfigDifferentHeader", + "TestRequestIDWithConfig", + "TestRequestID_IDNotAltered", + "TestRequestLoggerError", + "TestRequestLoggerOK", + "TestRequestLoggerWithConfig", + "TestRequestLoggerWithConfig_missingOnLogValuesPanics", + "TestRequestLogger_HandleError", + "TestRequestLogger_ID", + "TestRequestLogger_LogValuesFuncError", + "TestRequestLogger_allFields", + "TestRequestLogger_beforeNextFunc", + "TestRequestLogger_headerIsCaseInsensitive", + "TestRequestLogger_logError", + "TestRequestLogger_skipper", + "TestResolveResponseStatus", + "TestResponse", + "TestResponse_ChangeStatusCodeBeforeWrite", + "TestResponse_Flush", + "TestResponse_FlushPanics", + "TestResponse_Unwrap", + "TestResponse_UnwrapResponse", + "TestResponse_UnwrapResponse_error", + "TestResponse_Write_FallsBackToDefaultStatus", + "TestResponse_Write_UsesSetResponseCode", + "TestResponse_isHijacker", + "TestRewriteAfterRouting", + "TestRewriteURL", + "TestRewriteWithConfigPreMiddleware_Issue1143", + "TestRoundRobinBalancerWithNoTargets", + "TestRouteInfo", + "TestRouteInfo_Reverse", + "TestRouteMultiLevelBacktracking", + "TestRouteMultiLevelBacktracking2", + "TestRoute_ForGroup", + "TestRoute_ToRouteInfo", + "TestRouterAllowHeaderForAnyOtherMethodType", + "TestRouterAnyMatchesLastAddedAnyRoute", + "TestRouterAutoHandleHEADFullHTTPHandlerFlow", + "TestRouterAutoHandleHEAD_204Response", + "TestRouterAutoHandleHEAD_304Response", + "TestRouterAutoHandleHEAD_AnyRoute_NotWrapped", + "TestRouterAutoHandleHEAD_CatchAllRoute", + "TestRouterAutoHandleHEAD_ContentType", + "TestRouterAutoHandleHEAD_CustomResponseHeaders", + "TestRouterAutoHandleHEAD_ExplicitContentLength", + "TestRouterAutoHandleHEAD_HandlerError_ErrorHandlerRuns", + "TestRouterAutoHandleHEAD_MultipleWriteCalls", + "TestRouterAutoHandleHEAD_NoGetRoute_Returns405", + "TestRouterAutoHandleHEAD_PathParams", + "TestRouterAutoHandleHEAD_TransferEncoding", + "TestRouterAutoHandleHEAD_WithMiddleware", + "TestRouterBacktrackingFromMultipleParamKinds", + "TestRouterFillsRequestPatternField", + "TestRouterFindNotPanicOrLoopsWhenContextSetParamValuesIsCalledWithLessValuesThanEchoMaxParam", + "TestRouterGitHubAPI", + "TestRouterHandleMethodOptions", + "TestRouterIssue1348", + "TestRouterMatchAny", + "TestRouterMatchAnyMultiLevel", + "TestRouterMatchAnyMultiLevelWithPost", + "TestRouterMatchAnyPrefixIssue", + "TestRouterMatchAnySlash", + "TestRouterMicroParam", + "TestRouterMixParamMatchAny", + "TestRouterMixedParams", + "TestRouterMultiRoute", + "TestRouterNoRoutablePath", + "TestRouterOptionsMethodHandler", + "TestRouterPanicWhenParamNoRootOnlyChildsFailsFind", + "TestRouterParam", + "TestRouterParam1466", + "TestRouterParamAlias", + "TestRouterParamBacktraceNotFound", + "TestRouterParamNames", + "TestRouterParamOrdering", + "TestRouterParamStaticConflict", + "TestRouterParamWithSlash", + "TestRouterParam_escapeColon", + "TestRouterPriority", + "TestRouterPriorityNotFound", + "TestRouterStatic", + "TestRouterStaticDynamicConflict", + "TestRouterTwoParam", + "TestRouter_Match_DifferentParamNamesForSamePlace", + "TestRouter_ReverseNotFound", + "TestRouter_RouteWhenNotFoundRouteAnyKind", + "TestRouter_RouteWhenNotFoundRouteParamKind", + "TestRouter_RouteWhenNotFoundRouteStaticKind", + "TestRouter_RouteWhenNotFoundRouteWithNodeSplitting", + "TestRouter_Routes", + "TestRouter_addAndMatchAllSupportedMethods", + "TestRouter_addEmptyPathToSlashReverse", + "TestRoutes_Clone", + "TestRoutes_FilterByMethod", + "TestRoutes_FilterByName", + "TestRoutes_FilterByPath", + "TestRoutes_FindByMethodPath", + "TestRoutes_Reverse", + "TestRoutes_ReverseHandlerName", + "TestSecure", + "TestSecureWithConfig", + "TestSecureWithConfig_CSPReportOnly", + "TestSecureWithConfig_HSTSExcludeSubdomains", + "TestSecureWithConfig_HSTSPreloadEnabled", + "TestServeWithHandler", + "TestServeWithHandler_error", + "TestStartConfig_GracefulShutdown", + "TestStartConfig_Start", + "TestStartConfig_StartTLS", + "TestStartConfig_Start_createListenerError", + "TestStartConfig_WithBeforeServeFunc", + "TestStartConfig_WithHTTP2WithCustomTlsConfig", + "TestStartConfig_WithHideBanner", + "TestStartConfig_WithHidePort", + "TestStartConfig_WithListenerNetwork", + "TestStatic", + "TestStaticDirectoryHandlerAndRouterInconsistentEscaping", + "TestStaticDirectoryHandler_EncodedSeparatorDoesNotBypassRoute", + "TestStaticHTML5PreservesMatchedHandlerNotFound", + "TestStaticMiddlewareAndRouterInconsistentEscaping", + "TestStatic_CustomFS", + "TestStatic_DirectoryBrowsing", + "TestStatic_EncodedSeparatorDoesNotBypassRoute", + "TestStatic_percentEncodedTraversalIsBlocked", + "TestStatic_servesFileWithPercentInName", + "TestStatic_useCaseForApiAndSPAs", + "TestStatusCode", + "TestTargetProvider", + "TestTestRequestLogger", + "TestTimeFormatBinding", + "TestToContext_FormValues", + "TestToContext_Headers", + "TestToContext_JSONBody", + "TestToContext_MultipartForm", + "TestToContext_PathValues", + "TestToContext_QueryValues", + "TestToContext_RouteInfo", + "TestToMultipleFields", + "TestTrustIPRange", + "TestTrustLinkLocal", + "TestTrustLoopback", + "TestTrustPrivateNet", + "TestValidateOrigins", + "TestValueBinder_BindError", + "TestValueBinder_BindUnmarshaler", + "TestValueBinder_BindWithDelimiter", + "TestValueBinder_BindWithDelimiter_types", + "TestValueBinder_Bool", + "TestValueBinder_Bools", + "TestValueBinder_CustomFunc", + "TestValueBinder_CustomFuncWithError", + "TestValueBinder_Duration", + "TestValueBinder_DurationError", + "TestValueBinder_Durations", + "TestValueBinder_DurationsError", + "TestValueBinder_Float32", + "TestValueBinder_Float32s", + "TestValueBinder_Float64", + "TestValueBinder_Float64s", + "TestValueBinder_GetValues", + "TestValueBinder_Int64_intValue", + "TestValueBinder_Int64s_intsValue", + "TestValueBinder_Int_Types", + "TestValueBinder_Int_errorMessage", + "TestValueBinder_Ints_Types", + "TestValueBinder_Ints_Types_FailFast", + "TestValueBinder_JSONUnmarshaler", + "TestValueBinder_MustCustomFunc", + "TestValueBinder_String", + "TestValueBinder_Strings", + "TestValueBinder_TextUnmarshaler", + "TestValueBinder_Time", + "TestValueBinder_TimeError", + "TestValueBinder_Times", + "TestValueBinder_TimesError", + "TestValueBinder_Uint64_uintValue", + "TestValueBinder_Uint64s_uintsValue", + "TestValueBinder_UnixTime", + "TestValueBinder_UnixTimeMilli", + "TestValueBinder_UnixTimeNano", + "TestValueBinder_errorStopsBinding", + "TestValuesFromCookie", + "TestValuesFromForm", + "TestValuesFromHeader", + "TestValuesFromParam", + "TestValuesFromQuery", + "TestVirtualHostHandler", + "TestWrapHeadHandler_HandlerPanic_OriginalWriterRestored", + "TestWrapHeadHandler_PreservesCustomResponseHeaders", + "TestWrapHeadHandler_PropagatesHandlerError", + "TestWrapHeadHandler_RestoresOriginalWriterAfterHandler", + "TestWrapHeadHandler_RouteLevelMiddlewareSeesTrueCommitted", + "TestWrapHeadHandler_SuppressesBodyWrittenByHandler", + "Test_allowOriginFunc", + "Test_allowOriginScheme", + "Test_matchScheme" + ], + "test_modules": [], + "pass_to_pass": [ + "TestAddTrailingSlash", + "TestAddTrailingSlashWithConfig", + "TestAutoHeadExplicitHeadTakesPrecedence", + "TestBasicAuth", + "TestBasicAuthRealm", + "TestBasicAuthWithConfig_panic", + "TestBasicAuth_panic", + "TestBindCachedMetaPreservesFieldNameError", + "TestBindForm", + "TestBindHeaderParam", + "TestBindHeaderParamBadType", + "TestBindInt8", + "TestBindJSON", + "TestBindMultipartForm", + "TestBindMultipartFormFiles", + "TestBindParam", + "TestBindQueryParams", + "TestBindQueryParamsCaseInsensitive", + "TestBindQueryParamsCaseSensitivePrioritized", + "TestBindSetWithProperType", + "TestBindUnmarshalParam", + "TestBindUnmarshalParamAnonymousFieldPtr", + "TestBindUnmarshalParamAnonymousFieldPtrCustomTag", + "TestBindUnmarshalParamAnonymousFieldPtrNil", + "TestBindUnmarshalParamExtras", + "TestBindUnmarshalParamPtr", + "TestBindUnmarshalParams", + "TestBindUnmarshalText", + "TestBindUnmarshalTextPtr", + "TestBindUnmarshalTypeError", + "TestBindUnsupportedMediaType", + "TestBindWithDelimiter_invalidType", + "TestBindXML", + "TestBind_formConversionErrorIncludesFieldName", + "TestBindbindData", + "TestBindingError_Error", + "TestBindingError_ErrorJSON", + "TestBindingError_marshalJSON_emptyMessageFallsBackToStatusText", + "TestBindingError_serializesToStructuredJSON", + "TestBodyDump", + "TestBodyDumpResponseWriter_CanFlush", + "TestBodyDumpResponseWriter_CanHijack", + "TestBodyDumpResponseWriter_CanNotFlush", + "TestBodyDumpResponseWriter_CanNotHijack", + "TestBodyDumpResponseWriter_CanUnwrap", + "TestBodyDumpWithConfig_panic", + "TestBodyDump_BothLimitsSimultaneous", + "TestBodyDump_ClientGetsFullResponse", + "TestBodyDump_DefaultConfig", + "TestBodyDump_LargeRequestDosPrevention", + "TestBodyDump_LargeResponseDosPrevention", + "TestBodyDump_ReadError", + "TestBodyDump_RequestAtExactLimit", + "TestBodyDump_RequestExceedsLimit", + "TestBodyDump_RequestWithinLimit", + "TestBodyDump_ResponseExceedsLimit", + "TestBodyDump_ResponseWithinLimit", + "TestBodyDump_fails", + "TestBodyDump_panic", + "TestBodyDump_skipper", + "TestBodyLimit", + "TestBodyLimitAfterDecompressUsesDecodedSize", + "TestBodyLimitConfig_ToMiddleware", + "TestBodyLimitReader", + "TestBodyLimitWithConfig", + "TestBodyLimit_skipper", + "TestCORS", + "TestCORSConfig", + "TestCORSWithConfig_AllowMethods", + "TestCORS_NonPreflightOPTIONSPassThrough", + "TestCSRF", + "TestCSRFConfig_checkSecFetchSiteRequest", + "TestCSRFConfig_skipper", + "TestCSRFErrorHandling", + "TestCSRFSetSameSiteMode", + "TestCSRFWithConfig", + "TestCSRFWithSameSiteDefaultMode", + "TestCSRFWithSameSiteModeNone", + "TestCSRFWithoutSameSiteMode", + "TestCSRF_tokenExtractors", + "TestClientCancelConnectionResultsHTTPCode499", + "TestCompressRequestWithoutDecompressMiddleware", + "TestConcurrentRouter_ConcurrentReadWrite", + "TestConcurrentRouter_ConcurrentReads", + "TestConcurrentRouter_ConcurrentWrites", + "TestConcurrentRouter_ParametersNoRace", + "TestConcurrentRouter_Remove", + "TestConcurrentRouter_RoutesIterationDuringModification", + "TestContextAttachment", + "TestContextCookie", + "TestContextEcho", + "TestContextFormFile", + "TestContextFormValue", + "TestContextGet", + "TestContextGetAndSetPathValuesMutability", + "TestContextGetInvalidCast", + "TestContextGetNonExistentKey", + "TestContextGetOK", + "TestContextGetOrInvalidCast", + "TestContextGetOrNonExistentKey", + "TestContextGetOrOK", + "TestContextHTML", + "TestContextHTMLBlob", + "TestContextInline", + "TestContextJSON", + "TestContextJSONBlob", + "TestContextJSONErrorsOut", + "TestContextJSONP", + "TestContextJSONPBlob", + "TestContextJSONPretty", + "TestContextJSONStatusAcrossReset", + "TestContextJSONWithEmptyIntent", + "TestContextJSONWithNotEchoResponse", + "TestContextMultipartForm", + "TestContextNoContent", + "TestContextRedirect", + "TestContextRenderErrorsOnNoRenderer", + "TestContextRenderTemplate", + "TestContextRenderTemplateError", + "TestContextRequest", + "TestContextResetClearsStore", + "TestContextResponse", + "TestContextStream", + "TestContextTimeoutCanHandleContextDeadlineOnNextHandler", + "TestContextTimeoutErrorOutInHandler", + "TestContextTimeoutSkipper", + "TestContextTimeoutSuccessfulRequest", + "TestContextTimeoutTestRequestClone", + "TestContextTimeoutWithDefaultErrorMessage", + "TestContextTimeoutWithTimeout0", + "TestContextXML", + "TestContextXMLBlob", + "TestContextXMLPretty", + "TestContextXMLWithEmptyIntent", + "TestContext_Bind", + "TestContext_File", + "TestContext_FileFS", + "TestContext_IsWebSocket", + "TestContext_JSON_CommitsCustomResponseCode", + "TestContext_PathParam", + "TestContext_PathParamDefault", + "TestContext_PathValues", + "TestContext_QueryParam", + "TestContext_QueryParamDefault", + "TestContext_QueryParams", + "TestContext_QueryString", + "TestContext_RealIP", + "TestContext_Request", + "TestContext_Scheme", + "TestContext_SetParamNamesShouldNotModifyPathValuesCapacity", + "TestContext_Validate", + "TestCorsHeaders", + "TestCreateExtractors", + "TestDecompress", + "TestDecompressContentEncodingCaseInsensitive", + "TestDecompressErrorReturned", + "TestDecompressNoContent", + "TestDecompressPoolError", + "TestDecompressSkipper", + "TestDecompressWithConfig_DefaultConfig", + "TestDecompressWithConfig_DefaultConfig_noDecode", + "TestDecompress_AtExactLimit", + "TestDecompress_DefaultLimit", + "TestDecompress_ExceedsLimit", + "TestDecompress_LargePayloadDosPrevention", + "TestDecompress_MultipleReads", + "TestDecompress_SmallCustomLimit", + "TestDecompress_UnlimitedExplicit", + "TestDecompress_WithinLimit", + "TestDecompress_ZipBomb", + "TestDecompress_skippedIfNoHeader", + "TestDefaultBinder_BindBody", + "TestDefaultBinder_BindToStructFromMixedSources", + "TestDefaultBinder_bindDataToMap", + "TestDefaultHTTPErrorHandler", + "TestDefaultHTTPErrorHandler_CommitedResponse", + "TestDefaultJSONCodec_Decode", + "TestDefaultJSONCodec_Decode_BodyReadError", + "TestDefaultJSONCodec_Decode_LargeBodyThenNormal", + "TestDefaultJSONCodec_Decode_PooledBufferConcurrent", + "TestDefaultJSONCodec_Decode_PooledBufferReuse", + "TestDefaultJSONCodec_Decode_RejectsTrailingData", + "TestDefaultJSONCodec_Encode", + "TestDefaultRouter_AddDuplicateRouteAllowed", + "TestDefaultRouter_AddDuplicateRouteNotAllowed", + "TestDefaultRouter_AddWithoutHandler", + "TestDefaultRouter_MethodNotAllowedHandler", + "TestDefaultRouter_NotFoundHandler", + "TestDefaultRouter_OptionsMethodHandler", + "TestDefaultRouter_PathValuesCanMatchEmptyValues", + "TestDefaultRouter_Remove", + "TestDefaultRouter_UnescapePathParamValues", + "TestDefaultRouter_UseEscapedPathForRouting", + "TestEcho", + "TestEchoConnect", + "TestEchoContext", + "TestEchoDelete", + "TestEchoFile", + "TestEchoGet", + "TestEchoGroup", + "TestEchoHandler", + "TestEchoHead", + "TestEchoMatch", + "TestEchoMethodNotAllowed", + "TestEchoMiddleware", + "TestEchoMiddlewareError", + "TestEchoNotFound", + "TestEchoOptions", + "TestEchoPatch", + "TestEchoPost", + "TestEchoPut", + "TestEchoQuery", + "TestEchoRewritePreMiddleware", + "TestEchoRewriteReplacementEscaping", + "TestEchoRewriteWithCaret", + "TestEchoRewriteWithRegexRules", + "TestEchoServeHTTPPathEncoding", + "TestEchoStaticRedirectIndex", + "TestEchoTrace", + "TestEchoWrapHandler", + "TestEchoWrapMiddleware", + "TestEcho_Any", + "TestEcho_Any_hasLowerPriority", + "TestEcho_Any_matchesArbitraryMethod", + "TestEcho_FileFS", + "TestEcho_OnAddRoute", + "TestEcho_RouteNotFound", + "TestEcho_Start", + "TestEcho_StaticFS", + "TestEcho_StaticPanic", + "TestExtractIPDirect", + "TestExtractIPFromRealIPHeader", + "TestExtractIPFromXFFHeader", + "TestFailNextTarget", + "TestFilepathOrContent", + "TestFormFieldBinder", + "TestFormValue", + "TestFormValueOr", + "TestFormValue_UnsupportedType", + "TestFormValues", + "TestFormValuesOr", + "TestFormValues_UnsupportedType", + "TestFormat", + "TestGetRawQueryParamMatchesStdlib", + "TestGlobalMiddlewareRunsOnNotFoundAndMethodNotAllowed", + "TestGroupFile", + "TestGroupRouteMiddleware", + "TestGroupRouteMiddlewareWithMatchAny", + "TestGroupRoute_automaticOPTIONS", + "TestGroupRoute_catchAllMasksMethodHandling", + "TestGroupRoute_concreteRoutesResolve", + "TestGroupRoute_methodMismatchReturns405", + "TestGroupStaticFS_EncodedSeparatorDoesNotBypassRoute", + "TestGroup_Any", + "TestGroup_CONNECT", + "TestGroup_DELETE", + "TestGroup_FileFS", + "TestGroup_HEAD", + "TestGroup_Match", + "TestGroup_MatchWithErrors", + "TestGroup_OPTIONS", + "TestGroup_PATCH", + "TestGroup_POST", + "TestGroup_PUT", + "TestGroup_QUERY", + "TestGroup_RouteNotFound", + "TestGroup_RouteNotFoundUsesRouterConfig", + "TestGroup_RouteNotFoundWithMiddleware", + "TestGroup_Static", + "TestGroup_StaticMultiTest", + "TestGroup_StaticPanic", + "TestGroup_TRACE", + "TestGroup_UseMultipleTimes", + "TestGroup_doesNotAffectRootRoutes", + "TestGroup_multiLevelGroup", + "TestGroup_withRoutesWillExecuteMiddlewareFor404", + "TestGroup_withoutRouteWillExecuteMiddleware", + "TestGroup_withoutRouteWillNotExecuteMiddleware", + "TestGzipResponseWriter_CanHijack", + "TestGzipResponseWriter_CanNotHijack", + "TestGzipResponseWriter_CanUnwrap", + "TestGzipWithConfig_invalidLevel", + "TestGzipWithMinLength", + "TestGzipWithMinLengthChunked", + "TestGzipWithMinLengthNoContent", + "TestGzipWithMinLengthTooShort", + "TestGzipWithResponseWithoutBody", + "TestGzipWithStatic", + "TestGzip_AcceptEncodingHeader", + "TestGzip_Empty", + "TestGzip_ErrorReturned", + "TestGzip_NoAcceptEncodingHeader", + "TestGzip_NoContent", + "TestGzip_chunked", + "TestHTTPError_Error", + "TestHTTPError_StatusCode", + "TestHTTPError_WrapUnwrap", + "TestHandlerName", + "TestHeadResponseWriter_Commit_NoContentLength_1xx", + "TestHeadResponseWriter_Commit_NoContentLength_204", + "TestHeadResponseWriter_Commit_NoContentLength_304", + "TestHeadResponseWriter_Commit_NoContentLength_TransferEncoding", + "TestHeadResponseWriter_Commit_NoWriteHeader_WhenNotCommitted", + "TestHeadResponseWriter_Commit_PreservesExplicitContentLength", + "TestHeadResponseWriter_Commit_SetsContentLength", + "TestHeadResponseWriter_Flush_IsNoop", + "TestHeadResponseWriter_Header_DelegatesToUnderlying", + "TestHeadResponseWriter_Hijack_DelegatesToUnderlying", + "TestHeadResponseWriter_Unwrap_ReturnsUnderlying", + "TestHeadResponseWriter_WriteHeader_FirstCallWins", + "TestHeadResponseWriter_WriteHeader_SetsCommittedOnUnderlying", + "TestHeadResponseWriter_Write_CountsBytes", + "TestHeadResponseWriter_Write_ImpliesStatus200", + "TestHeadResponseWriter_Write_MultipleCallsSumBytes", + "TestIPChecker_TrustOption", + "TestIsCORSPreflight", + "TestKeyAuth", + "TestKeyAuthWithConfig", + "TestKeyAuthWithConfig_errors", + "TestKeyAuth_errorHandlerSwallowsError", + "TestLegacyIPExtractor", + "TestLoadBytesOK", + "TestLoadBytesOK_TrimNewlineEnd", + "TestLoadBytes_custom", + "TestLogger", + "TestMethodNotAllowedAndNotFound", + "TestMethodOverride", + "TestMethodOverride_formParam", + "TestMethodOverride_ignoreGet", + "TestMethodOverride_queryParam", + "TestMiddlewares", + "TestModifyResponseUseContext", + "TestMustGzipWithConfig_panics", + "TestMustKeyAuthWithConfig_panic", + "TestMustProxyWithConfig_emptyBalancerPanics", + "TestMustRateLimiterWithConfig_panicBehaviour", + "TestMustRequestIDWithConfig_RequestIDHandler", + "TestMustRequestIDWithConfig_customGenerator", + "TestMustRequestIDWithConfig_skipper", + "TestMustRewriteWithConfig_emptyRulesPanics", + "TestMustRewriteWithConfig_skipper", + "TestMustStaticWithConfig_panicsInvalidDirListTemplate", + "TestNestedJSONUsesFreshDelayedWriter", + "TestNewDefaultFS", + "TestNewHTTPError", + "TestNewRateLimiterMemoryStore", + "TestNewWithConfig", + "TestNonWWWRedirectWithConfig", + "TestParseValue_BindUnmarshaler", + "TestParseValue_Duration", + "TestParseValue_JSONUnmarshaler", + "TestParseValue_OptionsOnlyForTime", + "TestParseValue_TextUnmarshaler", + "TestParseValue_Time", + "TestParseValue_bool", + "TestParseValue_float32", + "TestParseValue_float64", + "TestParseValue_int", + "TestParseValue_int16", + "TestParseValue_int32", + "TestParseValue_int64", + "TestParseValue_int8", + "TestParseValue_string", + "TestParseValue_uint", + "TestParseValue_uint16", + "TestParseValue_uint32", + "TestParseValue_uint64", + "TestParseValue_uint8", + "TestParseValues_bools", + "TestPathParam", + "TestPathParamOr", + "TestPathParam_UnsupportedType", + "TestPathValuesBinder", + "TestPathValuesSizeOverMultipleRequests", + "TestPathValues_Get", + "TestPathValues_GetOr", + "TestPreMiddlewares", + "TestProblemDetailsHTTPErrorHandler", + "TestProblemDetailsHTTPErrorHandler_CommittedResponse", + "TestProblemDetailsHTTPErrorHandler_DoesNotMutateSharedProblem", + "TestProblemError_Error", + "TestProblemError_StatusCode", + "TestProxy", + "TestProxyError", + "TestProxyErrorHandler", + "TestProxyRealIPHeader", + "TestProxyRetries", + "TestProxyRetryWithBackendTimeout", + "TestProxyRewrite", + "TestProxyRewriteRegex", + "TestProxyWebSocketXForwardedFor", + "TestProxyWithConfigWebSocketNonTLS2NonTLS", + "TestProxyWithConfigWebSocketNonTLS2TLS", + "TestProxyWithConfigWebSocketTLS2NonTLS", + "TestProxyWithConfigWebSocketTLS2TLS", + "TestProxyWithNoTargetDoesNotRetry", + "TestProxyWithNoTargetReturnsBadGateway", + "TestQueryParam", + "TestQueryParamOr", + "TestQueryParam_UnsupportedType", + "TestQueryParams", + "TestQueryParamsBinder_FailFast", + "TestQueryParamsOr", + "TestQueryParams_UnsupportedType", + "TestRandomBalancerWithNoTargets", + "TestRandomString", + "TestRandomStringBias", + "TestRandomStringConcurrent", + "TestRateLimiter", + "TestRateLimiterMemoryStore_Allow", + "TestRateLimiterMemoryStore_AllowContextSetsHeaders", + "TestRateLimiterMemoryStore_ConcurrentAccess", + "TestRateLimiterMemoryStore_FractionalRateDefaultBurst", + "TestRateLimiterMemoryStore_RaceDetection", + "TestRateLimiterMemoryStore_TOCTOUFix", + "TestRateLimiterMemoryStore_TimeOrdering", + "TestRateLimiterMemoryStore_cleanupStaleVisitors", + "TestRateLimiterWithConfig", + "TestRateLimiterWithConfig_beforeFunc", + "TestRateLimiterWithConfig_defaultConfig", + "TestRateLimiterWithConfig_defaultDenyHandler", + "TestRateLimiterWithConfig_skipper", + "TestRateLimiterWithConfig_skipperNoSkip", + "TestRateLimiter_storeAllowContextIsPreferred", + "TestRecover", + "TestRecoverErrAbortHandler", + "TestRecoverWithConfig", + "TestRecover_skipper", + "TestRedirectHTTPSNonWWWRedirect", + "TestRedirectHTTPSRedirect", + "TestRedirectHTTPSWWWRedirect", + "TestRedirectNonWWWRedirect", + "TestRedirectWWWRedirect", + "TestRemoveTrailingSlash", + "TestRemoveTrailingSlashWithConfig", + "TestRenderWithTemplateRenderer", + "TestRequestID", + "TestRequestIDConfigDifferentHeader", + "TestRequestIDWithConfig", + "TestRequestID_IDNotAltered", + "TestRequestLoggerError", + "TestRequestLoggerOK", + "TestRequestLoggerWithConfig", + "TestRequestLoggerWithConfig_missingOnLogValuesPanics", + "TestRequestLogger_HandleError", + "TestRequestLogger_ID", + "TestRequestLogger_LogValuesFuncError", + "TestRequestLogger_allFields", + "TestRequestLogger_beforeNextFunc", + "TestRequestLogger_headerIsCaseInsensitive", + "TestRequestLogger_logError", + "TestRequestLogger_skipper", + "TestResolveResponseStatus", + "TestResponse", + "TestResponse_ChangeStatusCodeBeforeWrite", + "TestResponse_Flush", + "TestResponse_FlushPanics", + "TestResponse_Unwrap", + "TestResponse_UnwrapResponse", + "TestResponse_UnwrapResponse_error", + "TestResponse_Write_FallsBackToDefaultStatus", + "TestResponse_Write_UsesSetResponseCode", + "TestResponse_isHijacker", + "TestRewriteAfterRouting", + "TestRewriteURL", + "TestRewriteWithConfigPreMiddleware_Issue1143", + "TestRoundRobinBalancerWithNoTargets", + "TestRouteInfo", + "TestRouteInfo_Reverse", + "TestRouteMultiLevelBacktracking", + "TestRouteMultiLevelBacktracking2", + "TestRoute_ForGroup", + "TestRoute_ToRouteInfo", + "TestRouterAllowHeaderForAnyOtherMethodType", + "TestRouterAnyMatchesLastAddedAnyRoute", + "TestRouterAutoHandleHEADFullHTTPHandlerFlow", + "TestRouterAutoHandleHEAD_204Response", + "TestRouterAutoHandleHEAD_304Response", + "TestRouterAutoHandleHEAD_AnyRoute_NotWrapped", + "TestRouterAutoHandleHEAD_CatchAllRoute", + "TestRouterAutoHandleHEAD_ContentType", + "TestRouterAutoHandleHEAD_CustomResponseHeaders", + "TestRouterAutoHandleHEAD_ExplicitContentLength", + "TestRouterAutoHandleHEAD_HandlerError_ErrorHandlerRuns", + "TestRouterAutoHandleHEAD_MultipleWriteCalls", + "TestRouterAutoHandleHEAD_NoGetRoute_Returns405", + "TestRouterAutoHandleHEAD_PathParams", + "TestRouterAutoHandleHEAD_TransferEncoding", + "TestRouterAutoHandleHEAD_WithMiddleware", + "TestRouterBacktrackingFromMultipleParamKinds", + "TestRouterFillsRequestPatternField", + "TestRouterFindNotPanicOrLoopsWhenContextSetParamValuesIsCalledWithLessValuesThanEchoMaxParam", + "TestRouterGitHubAPI", + "TestRouterHandleMethodOptions", + "TestRouterIssue1348", + "TestRouterMatchAny", + "TestRouterMatchAnyMultiLevel", + "TestRouterMatchAnyMultiLevelWithPost", + "TestRouterMatchAnyPrefixIssue", + "TestRouterMatchAnySlash", + "TestRouterMicroParam", + "TestRouterMixParamMatchAny", + "TestRouterMixedParams", + "TestRouterMultiRoute", + "TestRouterNoRoutablePath", + "TestRouterOptionsMethodHandler", + "TestRouterPanicWhenParamNoRootOnlyChildsFailsFind", + "TestRouterParam", + "TestRouterParam1466", + "TestRouterParamAlias", + "TestRouterParamBacktraceNotFound", + "TestRouterParamNames", + "TestRouterParamOrdering", + "TestRouterParamStaticConflict", + "TestRouterParamWithSlash", + "TestRouterParam_escapeColon", + "TestRouterPriority", + "TestRouterPriorityNotFound", + "TestRouterStatic", + "TestRouterStaticDynamicConflict", + "TestRouterTwoParam", + "TestRouter_Match_DifferentParamNamesForSamePlace", + "TestRouter_ReverseNotFound", + "TestRouter_RouteWhenNotFoundRouteAnyKind", + "TestRouter_RouteWhenNotFoundRouteParamKind", + "TestRouter_RouteWhenNotFoundRouteStaticKind", + "TestRouter_RouteWhenNotFoundRouteWithNodeSplitting", + "TestRouter_Routes", + "TestRouter_addAndMatchAllSupportedMethods", + "TestRouter_addEmptyPathToSlashReverse", + "TestRoutes_Clone", + "TestRoutes_FilterByMethod", + "TestRoutes_FilterByName", + "TestRoutes_FilterByPath", + "TestRoutes_FindByMethodPath", + "TestRoutes_Reverse", + "TestRoutes_ReverseHandlerName", + "TestSecure", + "TestSecureWithConfig", + "TestSecureWithConfig_CSPReportOnly", + "TestSecureWithConfig_HSTSExcludeSubdomains", + "TestSecureWithConfig_HSTSPreloadEnabled", + "TestServeWithHandler", + "TestServeWithHandler_error", + "TestStartConfig_GracefulShutdown", + "TestStartConfig_Start", + "TestStartConfig_StartTLS", + "TestStartConfig_Start_createListenerError", + "TestStartConfig_WithBeforeServeFunc", + "TestStartConfig_WithHTTP2WithCustomTlsConfig", + "TestStartConfig_WithHideBanner", + "TestStartConfig_WithHidePort", + "TestStartConfig_WithListenerNetwork", + "TestStatic", + "TestStaticDirectoryHandlerAndRouterInconsistentEscaping", + "TestStaticDirectoryHandler_EncodedSeparatorDoesNotBypassRoute", + "TestStaticHTML5PreservesMatchedHandlerNotFound", + "TestStaticMiddlewareAndRouterInconsistentEscaping", + "TestStatic_CustomFS", + "TestStatic_DirectoryBrowsing", + "TestStatic_EncodedSeparatorDoesNotBypassRoute", + "TestStatic_percentEncodedTraversalIsBlocked", + "TestStatic_servesFileWithPercentInName", + "TestStatic_useCaseForApiAndSPAs", + "TestStatusCode", + "TestTargetProvider", + "TestTestRequestLogger", + "TestTimeFormatBinding", + "TestToContext_FormValues", + "TestToContext_Headers", + "TestToContext_JSONBody", + "TestToContext_MultipartForm", + "TestToContext_PathValues", + "TestToContext_QueryValues", + "TestToContext_RouteInfo", + "TestToMultipleFields", + "TestTrustIPRange", + "TestTrustLinkLocal", + "TestTrustLoopback", + "TestTrustPrivateNet", + "TestValidateOrigins", + "TestValueBinder_BindError", + "TestValueBinder_BindUnmarshaler", + "TestValueBinder_BindWithDelimiter", + "TestValueBinder_BindWithDelimiter_types", + "TestValueBinder_Bool", + "TestValueBinder_Bools", + "TestValueBinder_CustomFunc", + "TestValueBinder_CustomFuncWithError", + "TestValueBinder_Duration", + "TestValueBinder_DurationError", + "TestValueBinder_Durations", + "TestValueBinder_DurationsError", + "TestValueBinder_Float32", + "TestValueBinder_Float32s", + "TestValueBinder_Float64", + "TestValueBinder_Float64s", + "TestValueBinder_GetValues", + "TestValueBinder_Int64_intValue", + "TestValueBinder_Int64s_intsValue", + "TestValueBinder_Int_Types", + "TestValueBinder_Int_errorMessage", + "TestValueBinder_Ints_Types", + "TestValueBinder_Ints_Types_FailFast", + "TestValueBinder_JSONUnmarshaler", + "TestValueBinder_MustCustomFunc", + "TestValueBinder_String", + "TestValueBinder_Strings", + "TestValueBinder_TextUnmarshaler", + "TestValueBinder_Time", + "TestValueBinder_TimeError", + "TestValueBinder_Times", + "TestValueBinder_TimesError", + "TestValueBinder_Uint64_uintValue", + "TestValueBinder_Uint64s_uintsValue", + "TestValueBinder_UnixTime", + "TestValueBinder_UnixTimeMilli", + "TestValueBinder_UnixTimeNano", + "TestValueBinder_errorStopsBinding", + "TestValuesFromCookie", + "TestValuesFromForm", + "TestValuesFromHeader", + "TestValuesFromParam", + "TestValuesFromQuery", + "TestVirtualHostHandler", + "TestWrapHeadHandler_HandlerPanic_OriginalWriterRestored", + "TestWrapHeadHandler_PreservesCustomResponseHeaders", + "TestWrapHeadHandler_PropagatesHandlerError", + "TestWrapHeadHandler_RestoresOriginalWriterAfterHandler", + "TestWrapHeadHandler_RouteLevelMiddlewareSeesTrueCommitted", + "TestWrapHeadHandler_SuppressesBodyWrittenByHandler", + "Test_allowOriginFunc", + "Test_allowOriginScheme", + "Test_matchScheme" + ], + "gold_test_outcomes": { + "run": 634, + "passed": 634, + "failed": [] + }, + "validation": { + "gold": { + "resolved": true, + "sites_ok": true, + "green": true, + "n_run": 634 + }, + "empty": { + "resolved": false, + "sites_ok": false, + "missed_sites": 36 + }, + "partial": { + "resolved": false, + "sites_ok": false, + "green": false, + "missed_sites": 5, + "n_run": 423 + } + } +} \ No newline at end of file diff --git a/harness/tasks/e2e/deep__flask__add_url_rule_endpoint_required.json b/harness/tasks/e2e/deep__flask__add_url_rule_endpoint_required.json new file mode 100644 index 00000000..e9e9c5ac --- /dev/null +++ b/harness/tasks/e2e/deep__flask__add_url_rule_endpoint_required.json @@ -0,0 +1,606 @@ +{ + "instance_id": "deep__flask__add_url_rule_endpoint_required", + "repo": "pallets/flask", + "lang": "python", + "base_commit": "36e4a824f340fdee7ed50937ba8e7f6bc7d17f81", + "instruction": "Flask silently derives a URL rule's endpoint from the view function's name when `add_url_rule` is called without one, which hides endpoint collisions. Make the `endpoint` parameter of `add_url_rule` required -- remove its `= None` default (keep the annotation `str | None`; `route()` still hands over `None` when its decorator was given no endpoint) -- on every declaration: `Scaffold.add_url_rule` (flask/sansio/scaffold.py), `App.add_url_rule` (flask/sansio/app.py), `Blueprint.add_url_rule` and `BlueprintSetupState.add_url_rule` (flask/sansio/blueprints.py). Then update every call of `add_url_rule` in the repository that does not pass an endpoint (tests and type-check fixtures included): pass, as the second positional argument or as `endpoint=`, the exact name Flask derived before -- the view function's `__name__`, which for `SomeView.as_view(\"name\", ...)` is that `name`. Calls that already pass an endpoint stay as they are. Do not change `route()`'s signature or anything else; behavior must not change.", + "shapes": [ + { + "id": "auru/2", + "name": "add_url_rule", + "arity": 2 + }, + { + "id": "auru/3", + "name": "add_url_rule", + "arity": 3 + }, + { + "id": "endpoint=None", + "regex": "\\bendpoint:\\s*str\\s*\\|\\s*None\\s*=\\s*None" + } + ], + "source": "seeded", + "site_mode": "shapes", + "gold_tool": "build_deep.py recipe: declarations by pattern; every add_url_rule call without an endpoint found with the masked-text call finder (deep_edit), endpoint resolved from view_func (def name, as_view(name), or the as_view assignment it names); flask test suite in docker confirms", + "change": "make a defaulted parameter required (4 declarations); callers must pass the derived value", + "notes": "Shapes: calls of add_url_rule by argument count (a call missing its endpoint keeps a lower count than gold), plus the `endpoint: str | None = None` default on declarations. Calls that already passed an endpoint are identical in base and gold, so they cancel.", + "test_modules": [ + "tests" + ], + "kind": "wide", + "patch": "diff --git a/src/flask/sansio/app.py b/src/flask/sansio/app.py\nindex 74c5b323..0c5c4d07 100644\n--- a/src/flask/sansio/app.py\n+++ b/src/flask/sansio/app.py\n@@ -605,7 +605,7 @@ class App(Scaffold):\n def add_url_rule(\n self,\n rule: str,\n- endpoint: str | None = None,\n+ endpoint: str | None,\n view_func: ft.RouteCallable | None = None,\n provide_automatic_options: bool | None = None,\n **options: t.Any,\ndiff --git a/src/flask/sansio/blueprints.py b/src/flask/sansio/blueprints.py\nindex 665816e5..cced4a3a 100644\n--- a/src/flask/sansio/blueprints.py\n+++ b/src/flask/sansio/blueprints.py\n@@ -87,7 +87,7 @@ class BlueprintSetupState:\n def add_url_rule(\n self,\n rule: str,\n- endpoint: str | None = None,\n+ endpoint: str | None,\n view_func: ft.RouteCallable | None = None,\n **options: t.Any,\n ) -> None:\n@@ -413,7 +413,7 @@ class Blueprint(Scaffold):\n def add_url_rule(\n self,\n rule: str,\n- endpoint: str | None = None,\n+ endpoint: str | None,\n view_func: ft.RouteCallable | None = None,\n provide_automatic_options: bool | None = None,\n **options: t.Any,\ndiff --git a/src/flask/sansio/scaffold.py b/src/flask/sansio/scaffold.py\nindex a04c38ad..3e0cdb9e 100644\n--- a/src/flask/sansio/scaffold.py\n+++ b/src/flask/sansio/scaffold.py\n@@ -368,7 +368,7 @@ class Scaffold:\n def add_url_rule(\n self,\n rule: str,\n- endpoint: str | None = None,\n+ endpoint: str | None,\n view_func: ft.RouteCallable | None = None,\n provide_automatic_options: bool | None = None,\n **options: t.Any,\ndiff --git a/tests/test_async.py b/tests/test_async.py\nindex f52b0492..23d29c87 100644\n--- a/tests/test_async.py\n+++ b/tests/test_async.py\n@@ -72,8 +72,8 @@ def _async_app():\n \n app.register_blueprint(blueprint, url_prefix=\"/bp\")\n \n- app.add_url_rule(\"/view\", view_func=AsyncView.as_view(\"view\"))\n- app.add_url_rule(\"/methodview\", view_func=AsyncMethodView.as_view(\"methodview\"))\n+ app.add_url_rule(\"/view\", \"view\", view_func=AsyncView.as_view(\"view\"))\n+ app.add_url_rule(\"/methodview\", \"methodview\", view_func=AsyncMethodView.as_view(\"methodview\"))\n \n return app\n \ndiff --git a/tests/test_basic.py b/tests/test_basic.py\nindex 1d9d83f8..93e42a0c 100644\n--- a/tests/test_basic.py\n+++ b/tests/test_basic.py\n@@ -78,7 +78,7 @@ def test_provide_automatic_options_attr_disable(\n return \"Hello World!\"\n \n index.provide_automatic_options = False\n- app.add_url_rule(\"/\", view_func=index)\n+ app.add_url_rule(\"/\", \"index\", view_func=index)\n rv = client.options()\n assert rv.status_code == 405\n \n@@ -95,7 +95,7 @@ def test_provide_automatic_options_attr_enable(\n return \"Hello World!\"\n \n index.provide_automatic_options = True\n- app.add_url_rule(\"/\", view_func=index)\n+ app.add_url_rule(\"/\", \"index\", view_func=index)\n rv = client.options()\n assert rv.allow == {\"GET\", \"HEAD\", \"OPTIONS\"}\n \ndiff --git a/tests/test_blueprints.py b/tests/test_blueprints.py\nindex 6eb7d1d5..c39d5ac8 100644\n--- a/tests/test_blueprints.py\n+++ b/tests/test_blueprints.py\n@@ -330,7 +330,7 @@ def test_route_decorator_custom_endpoint_with_dots(app, client):\n view.__name__ = \"a.b\"\n \n with pytest.raises(ValueError):\n- bp.add_url_rule(\"/\", view_func=view)\n+ bp.add_url_rule(\"/\", \"view\", view_func=view)\n \n \n def test_endpoint_decorator(app, client):\ndiff --git a/tests/test_helpers.py b/tests/test_helpers.py\nindex c195b028..52f9fab5 100644\n--- a/tests/test_helpers.py\n+++ b/tests/test_helpers.py\n@@ -145,9 +145,9 @@ class TestUrlFor:\n return \"Create\"\n \n myview = MyView.as_view(\"myview\")\n- app.add_url_rule(\"/myview/\", methods=[\"GET\"], view_func=myview)\n- app.add_url_rule(\"/myview/\", methods=[\"GET\"], view_func=myview)\n- app.add_url_rule(\"/myview/create\", methods=[\"POST\"], view_func=myview)\n+ app.add_url_rule(\"/myview/\", \"myview\", methods=[\"GET\"], view_func=myview)\n+ app.add_url_rule(\"/myview/\", \"myview\", methods=[\"GET\"], view_func=myview)\n+ app.add_url_rule(\"/myview/create\", \"myview\", methods=[\"POST\"], view_func=myview)\n \n assert flask.url_for(\"myview\", _method=\"GET\") == \"/myview/\"\n assert flask.url_for(\"myview\", id=42, _method=\"GET\") == \"/myview/42\"\ndiff --git a/tests/test_views.py b/tests/test_views.py\nindex d002b504..73cd07c3 100644\n--- a/tests/test_views.py\n+++ b/tests/test_views.py\n@@ -22,7 +22,7 @@ def test_basic_view(app):\n def dispatch_request(self):\n return flask.request.method\n \n- app.add_url_rule(\"/\", view_func=Index.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=Index.as_view(\"index\"))\n common_test(app)\n \n \n@@ -34,7 +34,7 @@ def test_method_based_view(app):\n def post(self):\n return \"POST\"\n \n- app.add_url_rule(\"/\", view_func=Index.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=Index.as_view(\"index\"))\n \n common_test(app)\n \n@@ -56,7 +56,7 @@ def test_view_patching(app):\n \n view = Index.as_view(\"index\")\n view.view_class = Other\n- app.add_url_rule(\"/\", view_func=view)\n+ app.add_url_rule(\"/\", \"index\", view_func=view)\n common_test(app)\n \n \n@@ -72,7 +72,7 @@ def test_view_inheritance(app, client):\n def delete(self):\n return \"DELETE\"\n \n- app.add_url_rule(\"/\", view_func=BetterIndex.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=BetterIndex.as_view(\"index\"))\n \n meths = parse_set_header(client.open(\"/\", method=\"OPTIONS\").headers[\"Allow\"])\n assert sorted(meths) == [\"DELETE\", \"GET\", \"HEAD\", \"OPTIONS\", \"POST\"]\n@@ -93,7 +93,7 @@ def test_view_decorators(app, client):\n def dispatch_request(self):\n return \"Awesome\"\n \n- app.add_url_rule(\"/\", view_func=Index.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=Index.as_view(\"index\"))\n rv = client.get(\"/\")\n assert rv.headers[\"X-Parachute\"] == \"awesome\"\n assert rv.data == b\"Awesome\"\n@@ -110,7 +110,7 @@ def test_view_provide_automatic_options_attr_disable(\n def dispatch_request(self):\n return \"Hello World!\"\n \n- app.add_url_rule(\"/\", view_func=Index.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=Index.as_view(\"index\"))\n rv = client.options()\n assert rv.status_code == 405\n \n@@ -129,7 +129,7 @@ def test_view_provide_automatic_options_attr_enable(\n def dispatch_request(self):\n return \"Hello World!\"\n \n- app.add_url_rule(\"/\", view_func=Index.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=Index.as_view(\"index\"))\n rv = client.options(\"/\")\n assert rv.allow == {\"GET\", \"HEAD\", \"OPTIONS\"}\n \n@@ -145,7 +145,7 @@ def test_provide_automatic_options_method_disable(\n def dispatch_request(self):\n return \"\", {\"X-Test\": \"test\"}\n \n- app.add_url_rule(\"/\", view_func=Index.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=Index.as_view(\"index\"))\n rv = client.options()\n assert rv.headers[\"X-Test\"] == \"test\"\n \n@@ -155,7 +155,7 @@ def test_implicit_head(app, client):\n def get(self):\n return flask.Response(\"Blub\", headers={\"X-Method\": flask.request.method})\n \n- app.add_url_rule(\"/\", view_func=Index.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=Index.as_view(\"index\"))\n rv = client.get(\"/\")\n assert rv.data == b\"Blub\"\n assert rv.headers[\"X-Method\"] == \"GET\"\n@@ -172,7 +172,7 @@ def test_explicit_head(app, client):\n def head(self):\n return flask.Response(\"\", headers={\"X-Method\": \"HEAD\"})\n \n- app.add_url_rule(\"/\", view_func=Index.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=Index.as_view(\"index\"))\n rv = client.get(\"/\")\n assert rv.data == b\"GET\"\n rv = client.head(\"/\")\n@@ -189,10 +189,10 @@ def test_endpoint_override(app):\n def dispatch_request(self):\n return flask.request.method\n \n- app.add_url_rule(\"/\", view_func=Index.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=Index.as_view(\"index\"))\n \n with pytest.raises(AssertionError):\n- app.add_url_rule(\"/other\", view_func=Index.as_view(\"index\"))\n+ app.add_url_rule(\"/other\", \"index\", view_func=Index.as_view(\"index\"))\n \n # But these tests should still pass. We just log a warning.\n common_test(app)\n@@ -209,7 +209,7 @@ def test_methods_var_inheritance(app, client):\n def propfind(self):\n return \"PROPFIND\"\n \n- app.add_url_rule(\"/\", view_func=ChildView.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=ChildView.as_view(\"index\"))\n \n assert client.get(\"/\").data == b\"GET\"\n assert client.open(\"/\", method=\"PROPFIND\").data == b\"PROPFIND\"\n@@ -228,7 +228,7 @@ def test_multiple_inheritance(app, client):\n class GetDeleteView(GetView, DeleteView):\n pass\n \n- app.add_url_rule(\"/\", view_func=GetDeleteView.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=GetDeleteView.as_view(\"index\"))\n \n assert client.get(\"/\").data == b\"GET\"\n assert client.delete(\"/\").data == b\"DELETE\"\n@@ -247,7 +247,7 @@ def test_remove_method_from_parent(app, client):\n class View(GetView, OtherView):\n methods = [\"GET\"]\n \n- app.add_url_rule(\"/\", view_func=View.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=View.as_view(\"index\"))\n \n assert client.get(\"/\").data == b\"GET\"\n assert client.post(\"/\").status_code == 405\n@@ -267,6 +267,6 @@ def test_init_once(app, client):\n def dispatch_request(self):\n return str(n)\n \n- app.add_url_rule(\"/\", view_func=CountInit.as_view(\"index\"))\n+ app.add_url_rule(\"/\", \"index\", view_func=CountInit.as_view(\"index\"))\n assert client.get(\"/\").data == b\"1\"\n assert client.get(\"/\").data == b\"1\"\ndiff --git a/tests/type_check/typing_route.py b/tests/type_check/typing_route.py\nindex 8bc271b2..188056fe 100644\n--- a/tests/type_check/typing_route.py\n+++ b/tests/type_check/typing_route.py\n@@ -108,5 +108,5 @@ class RenderTemplateView(View):\n \n app.add_url_rule(\n \"/about\",\n- view_func=RenderTemplateView.as_view(\"about_page\", template_name=\"about.html\"),\n+ \"about_page\", view_func=RenderTemplateView.as_view(\"about_page\", template_name=\"about.html\"),\n )\n", + "test_patch": "", + "fail_to_pass": [], + "problem_statement": "Flask silently derives a URL rule's endpoint from the view function's name when `add_url_rule` is called without one, which hides endpoint collisions. Make the `endpoint` parameter of `add_url_rule` required -- remove its `= None` default (keep the annotation `str | None`; `route()` still hands over `None` when its decorator was given no endpoint) -- on every declaration: `Scaffold.add_url_rule` (flask/sansio/scaffold.py), `App.add_url_rule` (flask/sansio/app.py), `Blueprint.add_url_rule` and `BlueprintSetupState.add_url_rule` (flask/sansio/blueprints.py). Then update every call of `add_url_rule` in the repository that does not pass an endpoint (tests and type-check fixtures included): pass, as the second positional argument or as `endpoint=`, the exact name Flask derived before -- the view function's `__name__`, which for `SomeView.as_view(\"name\", ...)` is that `name`. Calls that already pass an endpoint stay as they are. Do not change `route()`'s signature or anything else; behavior must not change.", + "prompt_source": "wide-mandate", + "gold_files": [ + "src/flask/sansio/app.py", + "src/flask/sansio/blueprints.py", + "src/flask/sansio/scaffold.py", + "tests/test_async.py", + "tests/test_basic.py", + "tests/test_blueprints.py", + "tests/test_helpers.py", + "tests/test_views.py", + "tests/type_check/typing_route.py" + ], + "base_shape_counts": { + "auru/2": { + "examples/tutorial/flaskr/__init__.py": 1, + "tests/test_async.py": 2, + "tests/test_basic.py": 3, + "tests/test_blueprints.py": 2, + "tests/test_helpers.py": 1, + "tests/test_views.py": 16, + "tests/type_check/typing_route.py": 1 + }, + "auru/3": { + "src/flask/sansio/blueprints.py": 1, + "tests/test_basic.py": 4, + "tests/test_cli.py": 6, + "tests/test_helpers.py": 3, + "tests/test_json.py": 2 + }, + "endpoint=None": { + "src/flask/sansio/app.py": 1, + "src/flask/sansio/blueprints.py": 2, + "src/flask/sansio/scaffold.py": 1 + } + }, + "gold_shape_counts": { + "auru/2": { + "examples/tutorial/flaskr/__init__.py": 1, + "tests/test_basic.py": 1, + "tests/test_blueprints.py": 1, + "tests/test_helpers.py": 1 + }, + "auru/3": { + "src/flask/sansio/blueprints.py": 1, + "tests/test_async.py": 2, + "tests/test_basic.py": 6, + "tests/test_blueprints.py": 1, + "tests/test_cli.py": 6, + "tests/test_json.py": 2, + "tests/test_views.py": 16, + "tests/type_check/typing_route.py": 1 + }, + "endpoint=None": {} + }, + "gold_sites": 29, + "gold_site_files": 9, + "pass_to_pass": [ + "tests/test_appctx.py::test_app_context_provides_current_app", + "tests/test_appctx.py::test_app_ctx_globals_methods", + "tests/test_appctx.py::test_app_tearing_down", + "tests/test_appctx.py::test_app_tearing_down_with_handled_exception_by_app_handler", + "tests/test_appctx.py::test_app_tearing_down_with_handled_exception_by_except_block", + "tests/test_appctx.py::test_app_tearing_down_with_previous_exception", + "tests/test_appctx.py::test_app_tearing_down_with_unhandled_exception", + "tests/test_appctx.py::test_basic_url_generation", + "tests/test_appctx.py::test_clean_pop", + "tests/test_appctx.py::test_context_refcounts", + "tests/test_appctx.py::test_custom_app_ctx_globals_class", + "tests/test_appctx.py::test_request_context_means_app_context", + "tests/test_appctx.py::test_robust_teardown", + "tests/test_appctx.py::test_url_generation_requires_server_name", + "tests/test_appctx.py::test_url_generation_without_context_fails", + "tests/test_async.py::test_async_before_after_request", + "tests/test_async.py::test_async_error_handler[/bp/error]", + "tests/test_async.py::test_async_error_handler[/error]", + "tests/test_async.py::test_async_route[/]", + "tests/test_async.py::test_async_route[/bp/]", + "tests/test_async.py::test_async_route[/home]", + "tests/test_async.py::test_async_route[/methodview]", + "tests/test_async.py::test_async_route[/view]", + "tests/test_basic.py::test_after_request_processing", + "tests/test_basic.py::test_app_freed_on_zero_refcount", + "tests/test_basic.py::test_baseexception_error_handling", + "tests/test_basic.py::test_before_after_request_order", + "tests/test_basic.py::test_before_request_and_routing_errors", + "tests/test_basic.py::test_build_error_handler", + "tests/test_basic.py::test_build_error_handler_reraise", + "tests/test_basic.py::test_disallow_string_for_allowed_methods", + "tests/test_basic.py::test_enctype_debug_helper", + "tests/test_basic.py::test_endpoint_decorator", + "tests/test_basic.py::test_error_handler_after_processor_error", + "tests/test_basic.py::test_error_handling", + "tests/test_basic.py::test_error_handling_processing", + "tests/test_basic.py::test_errorhandler_precedence", + "tests/test_basic.py::test_exception_propagation[DEBUG]", + "tests/test_basic.py::test_exception_propagation[None]", + "tests/test_basic.py::test_exception_propagation[PROPAGATE_EXCEPTIONS]", + "tests/test_basic.py::test_exception_propagation[TESTING]", + "tests/test_basic.py::test_extended_flashing", + "tests/test_basic.py::test_flashes", + "tests/test_basic.py::test_g_iteration_protocol", + "tests/test_basic.py::test_get_method_on_g", + "tests/test_basic.py::test_http_error_subclass_handling", + "tests/test_basic.py::test_inject_blueprint_url_defaults", + "tests/test_basic.py::test_json_dump_dataclass", + "tests/test_basic.py::test_jsonify_args_and_kwargs_check", + "tests/test_basic.py::test_jsonify_mimetype", + "tests/test_basic.py::test_jsonify_no_prettyprint[False]", + "tests/test_basic.py::test_jsonify_no_prettyprint[True]", + "tests/test_basic.py::test_make_response", + "tests/test_basic.py::test_make_response_with_response_instance", + "tests/test_basic.py::test_max_cookie_size", + "tests/test_basic.py::test_method_route[delete]", + "tests/test_basic.py::test_method_route[get]", + "tests/test_basic.py::test_method_route[patch]", + "tests/test_basic.py::test_method_route[post]", + "tests/test_basic.py::test_method_route[put]", + "tests/test_basic.py::test_method_route_no_methods", + "tests/test_basic.py::test_missing_session", + "tests/test_basic.py::test_multi_route_class_views", + "tests/test_basic.py::test_multi_route_rules", + "tests/test_basic.py::test_no_setup_after_first_request", + "tests/test_basic.py::test_nonascii_pathinfo", + "tests/test_basic.py::test_options_on_multiple_rules", + "tests/test_basic.py::test_options_work", + "tests/test_basic.py::test_provide_automatic_options_arg_disable", + "tests/test_basic.py::test_provide_automatic_options_attr_disable", + "tests/test_basic.py::test_provide_automatic_options_attr_enable", + "tests/test_basic.py::test_provide_automatic_options_method_disable", + "tests/test_basic.py::test_request_dispatching", + "tests/test_basic.py::test_request_locals", + "tests/test_basic.py::test_request_preprocessing_early_return", + "tests/test_basic.py::test_request_processing", + "tests/test_basic.py::test_response_type_errors", + "tests/test_basic.py::test_response_types", + "tests/test_basic.py::test_route_decorator_custom_endpoint", + "tests/test_basic.py::test_routing_redirect_debugging", + "tests/test_basic.py::test_run_defaults", + "tests/test_basic.py::test_run_from_config[None-80-pocoo.org:8080-pocoo.org-80]", + "tests/test_basic.py::test_run_from_config[None-None-localhost:0-localhost-0]", + "tests/test_basic.py::test_run_from_config[None-None-localhost:8080-localhost-8080]", + "tests/test_basic.py::test_run_from_config[None-None-pocoo.org:8080-pocoo.org-8080]", + "tests/test_basic.py::test_run_from_config[localhost-0-localhost:8080-localhost-0]", + "tests/test_basic.py::test_run_from_config[localhost-80-pocoo.org:8080-localhost-80]", + "tests/test_basic.py::test_run_from_config[localhost-None-pocoo.org:8080-localhost-8080]", + "tests/test_basic.py::test_run_server_port", + "tests/test_basic.py::test_server_name_matching[False-False-default-default]", + "tests/test_basic.py::test_server_name_matching[False-True-abc-default]", + "tests/test_basic.py::test_server_name_matching[True-False-abc-]", + "tests/test_basic.py::test_server_name_subdomain", + "tests/test_basic.py::test_session_accessed", + "tests/test_basic.py::test_session_cookie_setting", + "tests/test_basic.py::test_session_expiration", + "tests/test_basic.py::test_session_path", + "tests/test_basic.py::test_session_refresh_vary", + "tests/test_basic.py::test_session_secret_key_fallbacks", + "tests/test_basic.py::test_session_special_types", + "tests/test_basic.py::test_session_stored_last", + "tests/test_basic.py::test_session_using_application_root", + "tests/test_basic.py::test_session_using_samesite_attribute", + "tests/test_basic.py::test_session_using_session_settings", + "tests/test_basic.py::test_session_vary_cookie", + "tests/test_basic.py::test_static_files", + "tests/test_basic.py::test_static_folder_with_ending_slash", + "tests/test_basic.py::test_static_folder_with_pathlib_path", + "tests/test_basic.py::test_static_route_with_host_matching", + "tests/test_basic.py::test_static_url_empty_path", + "tests/test_basic.py::test_static_url_empty_path_default", + "tests/test_basic.py::test_static_url_path", + "tests/test_basic.py::test_static_url_path_with_ending_slash", + "tests/test_basic.py::test_subdomain_basic_support", + "tests/test_basic.py::test_subdomain_matching", + "tests/test_basic.py::test_subdomain_matching_other_name[False]", + "tests/test_basic.py::test_subdomain_matching_other_name[True]", + "tests/test_basic.py::test_subdomain_matching_with_ports", + "tests/test_basic.py::test_teardown_request_handler", + "tests/test_basic.py::test_teardown_request_handler_debug_mode", + "tests/test_basic.py::test_teardown_request_handler_error", + "tests/test_basic.py::test_trap_bad_request_key_error[False-None-True-True]", + "tests/test_basic.py::test_trap_bad_request_key_error[False-True-False-False]", + "tests/test_basic.py::test_trap_bad_request_key_error[True-None-False-True]", + "tests/test_basic.py::test_trapping_of_all_http_exceptions", + "tests/test_basic.py::test_url_for_passes_special_values_to_build_error_handler", + "tests/test_basic.py::test_url_generation", + "tests/test_basic.py::test_url_mapping", + "tests/test_basic.py::test_url_processors", + "tests/test_basic.py::test_user_error_handling", + "tests/test_basic.py::test_werkzeug_passthrough_errors[False-False-False-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[False-False-False-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[False-False-True-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[False-False-True-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[False-True-False-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[False-True-False-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[False-True-True-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[False-True-True-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[None-False-False-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[None-False-False-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[None-False-True-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[None-False-True-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[None-True-False-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[None-True-False-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[None-True-True-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[None-True-True-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[True-False-False-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[True-False-False-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[True-False-True-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[True-False-True-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[True-True-False-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[True-True-False-True]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[True-True-True-False]", + "tests/test_basic.py::test_werkzeug_passthrough_errors[True-True-True-True]", + "tests/test_basic.py::test_werkzeug_routing", + "tests/test_blueprints.py::test_add_template_filter", + "tests/test_blueprints.py::test_add_template_filter_with_name", + "tests/test_blueprints.py::test_add_template_filter_with_name_and_template", + "tests/test_blueprints.py::test_add_template_filter_with_template", + "tests/test_blueprints.py::test_add_template_test", + "tests/test_blueprints.py::test_add_template_test_with_name", + "tests/test_blueprints.py::test_add_template_test_with_name_and_template", + "tests/test_blueprints.py::test_add_template_test_with_template", + "tests/test_blueprints.py::test_app_request_processing", + "tests/test_blueprints.py::test_app_url_processors", + "tests/test_blueprints.py::test_blueprint_app_error_handling", + "tests/test_blueprints.py::test_blueprint_prefix_slash[-/-/]", + "tests/test_blueprints.py::test_blueprint_prefix_slash[-/bar-/bar]", + "tests/test_blueprints.py::test_blueprint_prefix_slash[/--/]", + "tests/test_blueprints.py::test_blueprint_prefix_slash[/-/-/]", + "tests/test_blueprints.py::test_blueprint_prefix_slash[/foo--/foo]", + "tests/test_blueprints.py::test_blueprint_prefix_slash[/foo-/bar-/foo/bar]", + "tests/test_blueprints.py::test_blueprint_prefix_slash[/foo/--/foo/]", + "tests/test_blueprints.py::test_blueprint_prefix_slash[/foo/-//bar-/foo/bar]", + "tests/test_blueprints.py::test_blueprint_prefix_slash[/foo/-/bar-/foo/bar]", + "tests/test_blueprints.py::test_blueprint_prefix_slash[/foo/-bar-/foo/bar]", + "tests/test_blueprints.py::test_blueprint_prefix_slash[/foo//-/bar-/foo/bar]", + "tests/test_blueprints.py::test_blueprint_renaming", + "tests/test_blueprints.py::test_blueprint_specific_error_handling", + "tests/test_blueprints.py::test_blueprint_specific_user_error_handling", + "tests/test_blueprints.py::test_blueprint_url_defaults", + "tests/test_blueprints.py::test_blueprint_url_processors", + "tests/test_blueprints.py::test_child_and_parent_subdomain", + "tests/test_blueprints.py::test_context_processing", + "tests/test_blueprints.py::test_default_static_max_age", + "tests/test_blueprints.py::test_dotted_name_not_allowed", + "tests/test_blueprints.py::test_dotted_names_from_app", + "tests/test_blueprints.py::test_empty_name_not_allowed", + "tests/test_blueprints.py::test_empty_url_defaults", + "tests/test_blueprints.py::test_endpoint_decorator", + "tests/test_blueprints.py::test_nested_blueprint", + "tests/test_blueprints.py::test_nested_callback_order", + "tests/test_blueprints.py::test_nesting_subdomains", + "tests/test_blueprints.py::test_nesting_url_prefixes[/other-/something-/parent-/child]", + "tests/test_blueprints.py::test_nesting_url_prefixes[/parent-/child-None-None]", + "tests/test_blueprints.py::test_nesting_url_prefixes[/parent-None-None-/child]", + "tests/test_blueprints.py::test_nesting_url_prefixes[None-None-/parent-/child]", + "tests/test_blueprints.py::test_request_processing", + "tests/test_blueprints.py::test_route_decorator_custom_endpoint", + "tests/test_blueprints.py::test_route_decorator_custom_endpoint_with_dots", + "tests/test_blueprints.py::test_self_registration", + "tests/test_blueprints.py::test_template_filter", + "tests/test_blueprints.py::test_template_filter_after_route_with_template", + "tests/test_blueprints.py::test_template_filter_with_name", + "tests/test_blueprints.py::test_template_filter_with_name_and_template", + "tests/test_blueprints.py::test_template_filter_with_template", + "tests/test_blueprints.py::test_template_global", + "tests/test_blueprints.py::test_template_test", + "tests/test_blueprints.py::test_template_test_after_route_with_template", + "tests/test_blueprints.py::test_template_test_with_name", + "tests/test_blueprints.py::test_template_test_with_name_and_template", + "tests/test_blueprints.py::test_template_test_with_template", + "tests/test_blueprints.py::test_templates_and_static", + "tests/test_blueprints.py::test_templates_list", + "tests/test_blueprints.py::test_unique_blueprint_names", + "tests/test_cli.py::TestRoutes::test_all_methods", + "tests/test_cli.py::TestRoutes::test_host", + "tests/test_cli.py::TestRoutes::test_no_routes", + "tests/test_cli.py::TestRoutes::test_simple", + "tests/test_cli.py::TestRoutes::test_sort", + "tests/test_cli.py::TestRoutes::test_subdomain", + "tests/test_cli.py::test_app_cli_has_app_context", + "tests/test_cli.py::test_appgroup_app_context", + "tests/test_cli.py::test_cli_blueprints", + "tests/test_cli.py::test_cli_empty", + "tests/test_cli.py::test_cli_name", + "tests/test_cli.py::test_disable_dotenv_from_env", + "tests/test_cli.py::test_dotenv_optional", + "tests/test_cli.py::test_dotenv_path", + "tests/test_cli.py::test_find_best_app", + "tests/test_cli.py::test_flaskgroup_app_context", + "tests/test_cli.py::test_flaskgroup_debug[False]", + "tests/test_cli.py::test_flaskgroup_debug[True]", + "tests/test_cli.py::test_flaskgroup_nested", + "tests/test_cli.py::test_get_version", + "tests/test_cli.py::test_help_echo_exception", + "tests/test_cli.py::test_help_echo_loading_error", + "tests/test_cli.py::test_load_dotenv", + "tests/test_cli.py::test_locate_app[cliapp.app-None-testapp]", + "tests/test_cli.py::test_locate_app[cliapp.app-testapp-testapp]", + "tests/test_cli.py::test_locate_app[cliapp.factory-None-app]", + "tests/test_cli.py::test_locate_app[cliapp.factory-create_app()-app]", + "tests/test_cli.py::test_locate_app[cliapp.factory-create_app-app]", + "tests/test_cli.py::test_locate_app_raises[cliapp.app-notanapp]", + "tests/test_cli.py::test_locate_app_raises[cliapp.factory-create_app(]", + "tests/test_cli.py::test_locate_app_raises[cliapp.factory-create_app2(\"foo\")]", + "tests/test_cli.py::test_locate_app_raises[cliapp.factory-no_app]", + "tests/test_cli.py::test_locate_app_raises[cliapp.importerrorapp-None]", + "tests/test_cli.py::test_locate_app_raises[cliapp.message.txt-None]", + "tests/test_cli.py::test_locate_app_raises[cliapp/app-None]", + "tests/test_cli.py::test_locate_app_raises[notanapp.py-None]", + "tests/test_cli.py::test_locate_app_suppress_raise", + "tests/test_cli.py::test_no_command_echo_loading_error", + "tests/test_cli.py::test_prepare_import[a/test-path2-test]", + "tests/test_cli.py::test_prepare_import[test-path0-test]", + "tests/test_cli.py::test_prepare_import[test.a.b-path7-test.a.b]", + "tests/test_cli.py::test_prepare_import[test.py-path1-test]", + "tests/test_cli.py::test_prepare_import[test/__init__-path4-test]", + "tests/test_cli.py::test_prepare_import[test/__init__.py-path3-test]", + "tests/test_cli.py::test_prepare_import[value5-path5-cliapp.inner1]", + "tests/test_cli.py::test_prepare_import[value6-path6-cliapp.inner1.inner2]", + "tests/test_cli.py::test_prepare_import[value8-path8-cliapp.app]", + "tests/test_cli.py::test_prepare_import[value9-path9-cliapp.message.txt]", + "tests/test_cli.py::test_run_cert_adhoc", + "tests/test_cli.py::test_run_cert_import", + "tests/test_cli.py::test_run_cert_no_ssl", + "tests/test_cli.py::test_run_cert_path", + "tests/test_cli.py::test_run_exclude_patterns", + "tests/test_cli.py::test_scriptinfo", + "tests/test_cli.py::test_with_appcontext", + "tests/test_config.py::test_config_from_class", + "tests/test_config.py::test_config_from_envvar", + "tests/test_config.py::test_config_from_envvar_missing", + "tests/test_config.py::test_config_from_file_json", + "tests/test_config.py::test_config_from_file_toml", + "tests/test_config.py::test_config_from_mapping", + "tests/test_config.py::test_config_from_object", + "tests/test_config.py::test_config_from_pyfile", + "tests/test_config.py::test_config_missing", + "tests/test_config.py::test_config_missing_file", + "tests/test_config.py::test_custom_config_class", + "tests/test_config.py::test_from_prefixed_env", + "tests/test_config.py::test_from_prefixed_env_custom_prefix", + "tests/test_config.py::test_from_prefixed_env_nested", + "tests/test_config.py::test_from_pyfile_weird_encoding[iso-8859-15]", + "tests/test_config.py::test_from_pyfile_weird_encoding[latin-1]", + "tests/test_config.py::test_from_pyfile_weird_encoding[utf-8]", + "tests/test_config.py::test_get_namespace", + "tests/test_config.py::test_session_lifetime", + "tests/test_converters.py::test_context_available", + "tests/test_converters.py::test_custom_converters", + "tests/test_helpers.py::TestHelpers::test_get_debug_flag[-False]", + "tests/test_helpers.py::TestHelpers::test_get_debug_flag[0-False]", + "tests/test_helpers.py::TestHelpers::test_get_debug_flag[False-False]", + "tests/test_helpers.py::TestHelpers::test_get_debug_flag[No-False]", + "tests/test_helpers.py::TestHelpers::test_get_debug_flag[True-True]", + "tests/test_helpers.py::TestHelpers::test_make_response", + "tests/test_helpers.py::TestNoImports::test_name_with_import_error", + "tests/test_helpers.py::TestSendfile::test_send_file", + "tests/test_helpers.py::TestSendfile::test_send_from_directory", + "tests/test_helpers.py::TestSendfile::test_static_file", + "tests/test_helpers.py::TestStreaming::test_async_view", + "tests/test_helpers.py::TestStreaming::test_stream_keeps_session", + "tests/test_helpers.py::TestStreaming::test_streaming_with_context", + "tests/test_helpers.py::TestStreaming::test_streaming_with_context_and_custom_close", + "tests/test_helpers.py::TestStreaming::test_streaming_with_context_as_decorator", + "tests/test_helpers.py::TestUrlFor::test_url_for_with_alternating_schemes", + "tests/test_helpers.py::TestUrlFor::test_url_for_with_anchor", + "tests/test_helpers.py::TestUrlFor::test_url_for_with_scheme", + "tests/test_helpers.py::TestUrlFor::test_url_for_with_scheme_not_external", + "tests/test_helpers.py::TestUrlFor::test_url_for_with_self", + "tests/test_helpers.py::TestUrlFor::test_url_with_method", + "tests/test_helpers.py::test_abort_no_app", + "tests/test_helpers.py::test_abort_with_app", + "tests/test_helpers.py::test_app_aborter_class", + "tests/test_helpers.py::test_open_resource[r]", + "tests/test_helpers.py::test_open_resource[rb]", + "tests/test_helpers.py::test_open_resource[rt]", + "tests/test_helpers.py::test_open_resource_exceptions[a]", + "tests/test_helpers.py::test_open_resource_exceptions[r+]", + "tests/test_helpers.py::test_open_resource_exceptions[w]", + "tests/test_helpers.py::test_open_resource_exceptions[x]", + "tests/test_helpers.py::test_open_resource_with_encoding[utf-16-le]", + "tests/test_helpers.py::test_open_resource_with_encoding[utf-8]", + "tests/test_helpers.py::test_redirect_no_app", + "tests/test_helpers.py::test_redirect_with_app", + "tests/test_instance_config.py::test_explicit_instance_paths", + "tests/test_instance_config.py::test_installed_module_paths", + "tests/test_instance_config.py::test_installed_package_paths", + "tests/test_instance_config.py::test_prefix_package_paths", + "tests/test_instance_config.py::test_uninstalled_module_paths", + "tests/test_instance_config.py::test_uninstalled_namespace_paths", + "tests/test_instance_config.py::test_uninstalled_package_paths", + "tests/test_json.py::test_bad_request_debug_message[False]", + "tests/test_json.py::test_bad_request_debug_message[True]", + "tests/test_json.py::test_html_method", + "tests/test_json.py::test_json_as_unicode[False-\"\\u2603\"]", + "tests/test_json.py::test_json_as_unicode[True-\"\\\\u2603\"]", + "tests/test_json.py::test_json_attr", + "tests/test_json.py::test_json_bad_requests", + "tests/test_json.py::test_json_custom_mimetypes", + "tests/test_json.py::test_json_customization", + "tests/test_json.py::test_json_decimal", + "tests/test_json.py::test_json_dump_to_file", + "tests/test_json.py::test_json_key_sorting", + "tests/test_json.py::test_jsonify_arrays", + "tests/test_json.py::test_jsonify_aware_datetimes[tz0]", + "tests/test_json.py::test_jsonify_aware_datetimes[tz1]", + "tests/test_json.py::test_jsonify_aware_datetimes[tz2]", + "tests/test_json.py::test_jsonify_basic_types[-1]", + "tests/test_json.py::test_jsonify_basic_types[0]", + "tests/test_json.py::test_jsonify_basic_types[1]", + "tests/test_json.py::test_jsonify_basic_types[23]", + "tests/test_json.py::test_jsonify_basic_types[3.14]", + "tests/test_json.py::test_jsonify_basic_types[False]", + "tests/test_json.py::test_jsonify_basic_types[None]", + "tests/test_json.py::test_jsonify_basic_types[True]", + "tests/test_json.py::test_jsonify_basic_types[s]", + "tests/test_json.py::test_jsonify_datetime[value0]", + "tests/test_json.py::test_jsonify_datetime[value1]", + "tests/test_json.py::test_jsonify_dicts", + "tests/test_json.py::test_jsonify_uuid_types", + "tests/test_json.py::test_tojson_filter", + "tests/test_json_tag.py::test_custom_tag", + "tests/test_json_tag.py::test_dump_load_unchanged[]", + "tests/test_json_tag.py::test_dump_load_unchanged[\\xff]", + "tests/test_json_tag.py::test_dump_load_unchanged[data0]", + "tests/test_json_tag.py::test_dump_load_unchanged[data1]", + "tests/test_json_tag.py::test_dump_load_unchanged[data2]", + "tests/test_json_tag.py::test_dump_load_unchanged[data3]", + "tests/test_json_tag.py::test_dump_load_unchanged[data4]", + "tests/test_json_tag.py::test_dump_load_unchanged[data5]", + "tests/test_json_tag.py::test_dump_load_unchanged[data8]", + "tests/test_json_tag.py::test_dump_load_unchanged[data9]", + "tests/test_json_tag.py::test_duplicate_tag", + "tests/test_json_tag.py::test_tag_interface", + "tests/test_json_tag.py::test_tag_order", + "tests/test_logging.py::test_existing_handler", + "tests/test_logging.py::test_has_level_handler", + "tests/test_logging.py::test_log_view_exception", + "tests/test_logging.py::test_logger", + "tests/test_logging.py::test_logger_debug", + "tests/test_logging.py::test_wsgi_errors_stream", + "tests/test_regression.py::test_aborting", + "tests/test_reqctx.py::test_context_binding", + "tests/test_reqctx.py::test_context_test", + "tests/test_reqctx.py::test_copy_context_thread", + "tests/test_reqctx.py::test_manual_context_binding", + "tests/test_reqctx.py::test_proper_test_request_context", + "tests/test_reqctx.py::test_session_dynamic_cookie_name", + "tests/test_reqctx.py::test_session_error_pops_context", + "tests/test_reqctx.py::test_teardown_on_pop", + "tests/test_reqctx.py::test_teardown_with_handled_exception", + "tests/test_reqctx.py::test_teardown_with_previous_exception", + "tests/test_request.py::test_limit_config", + "tests/test_request.py::test_max_content_length", + "tests/test_request.py::test_trusted_hosts_config", + "tests/test_session_interface.py::test_open_session_with_endpoint", + "tests/test_signals.py::test_appcontext_signals", + "tests/test_signals.py::test_appcontext_tearing_down_signal", + "tests/test_signals.py::test_before_render_template", + "tests/test_signals.py::test_flash_signal", + "tests/test_signals.py::test_request_exception_signal", + "tests/test_signals.py::test_request_signals", + "tests/test_signals.py::test_template_rendered", + "tests/test_subclassing.py::test_suppressed_exception_logging", + "tests/test_templating.py::test_add_template_filter", + "tests/test_templating.py::test_add_template_filter_with_name", + "tests/test_templating.py::test_add_template_filter_with_name_and_template", + "tests/test_templating.py::test_add_template_filter_with_template", + "tests/test_templating.py::test_add_template_global", + "tests/test_templating.py::test_add_template_test", + "tests/test_templating.py::test_add_template_test_with_name", + "tests/test_templating.py::test_add_template_test_with_name_and_template", + "tests/test_templating.py::test_add_template_test_with_template", + "tests/test_templating.py::test_context_processing", + "tests/test_templating.py::test_custom_jinja_env", + "tests/test_templating.py::test_custom_template_loader", + "tests/test_templating.py::test_escaping", + "tests/test_templating.py::test_escaping_without_template_filename", + "tests/test_templating.py::test_iterable_loader", + "tests/test_templating.py::test_macros", + "tests/test_templating.py::test_no_escaping", + "tests/test_templating.py::test_original_win", + "tests/test_templating.py::test_request_less_rendering", + "tests/test_templating.py::test_simple_stream", + "tests/test_templating.py::test_standard_context", + "tests/test_templating.py::test_template_filter", + "tests/test_templating.py::test_template_filter_with_name", + "tests/test_templating.py::test_template_filter_with_name_and_template", + "tests/test_templating.py::test_template_filter_with_template", + "tests/test_templating.py::test_template_loader_debugging", + "tests/test_templating.py::test_template_test", + "tests/test_templating.py::test_template_test_with_name", + "tests/test_templating.py::test_template_test_with_name_and_template", + "tests/test_templating.py::test_template_test_with_template", + "tests/test_templating.py::test_templates_auto_reload", + "tests/test_templating.py::test_templates_auto_reload_debug_run", + "tests/test_testing.py::test_blueprint_with_subdomain", + "tests/test_testing.py::test_cli_custom_obj", + "tests/test_testing.py::test_cli_invoke", + "tests/test_testing.py::test_cli_runner_class", + "tests/test_testing.py::test_client_json_no_app_context", + "tests/test_testing.py::test_client_open_environ", + "tests/test_testing.py::test_client_pop_all_preserved", + "tests/test_testing.py::test_environ_base_default", + "tests/test_testing.py::test_environ_base_modified", + "tests/test_testing.py::test_environ_defaults", + "tests/test_testing.py::test_environ_defaults_from_config", + "tests/test_testing.py::test_environbuilder_json_dumps", + "tests/test_testing.py::test_full_url_request", + "tests/test_testing.py::test_json_request_and_response", + "tests/test_testing.py::test_nosubdomain", + "tests/test_testing.py::test_path_is_url", + "tests/test_testing.py::test_redirect_session", + "tests/test_testing.py::test_reuse_client", + "tests/test_testing.py::test_session_transaction_needs_cookies", + "tests/test_testing.py::test_session_transactions", + "tests/test_testing.py::test_session_transactions_keep_context", + "tests/test_testing.py::test_session_transactions_no_null_sessions", + "tests/test_testing.py::test_specify_url_scheme", + "tests/test_testing.py::test_subdomain", + "tests/test_testing.py::test_test_client_context_binding", + "tests/test_user_error_handler.py::TestGenericHandlers::test_handle_class_or_code[500]", + "tests/test_user_error_handler.py::TestGenericHandlers::test_handle_class_or_code[InternalServerError]", + "tests/test_user_error_handler.py::TestGenericHandlers::test_handle_generic", + "tests/test_user_error_handler.py::TestGenericHandlers::test_handle_generic_http", + "tests/test_user_error_handler.py::test_default_error_handler", + "tests/test_user_error_handler.py::test_error_handler_blueprint", + "tests/test_user_error_handler.py::test_error_handler_http_subclass", + "tests/test_user_error_handler.py::test_error_handler_no_match", + "tests/test_user_error_handler.py::test_error_handler_subclass", + "tests/test_views.py::test_basic_view", + "tests/test_views.py::test_endpoint_override", + "tests/test_views.py::test_explicit_head", + "tests/test_views.py::test_implicit_head", + "tests/test_views.py::test_init_once", + "tests/test_views.py::test_method_based_view", + "tests/test_views.py::test_methods_var_inheritance", + "tests/test_views.py::test_multiple_inheritance", + "tests/test_views.py::test_provide_automatic_options_method_disable", + "tests/test_views.py::test_remove_method_from_parent", + "tests/test_views.py::test_view_decorators", + "tests/test_views.py::test_view_inheritance", + "tests/test_views.py::test_view_patching", + "tests/test_views.py::test_view_provide_automatic_options_attr_disable", + "tests/test_views.py::test_view_provide_automatic_options_attr_enable" + ], + "gold_test_outcomes": { + "run": 487, + "passed": 487, + "failed": [] + }, + "validation": { + "gold": { + "resolved": true, + "sites_ok": true, + "green": true, + "n_run": 487 + }, + "empty": { + "resolved": false, + "sites_ok": false, + "missed_sites": 29 + }, + "partial": { + "resolved": false, + "sites_ok": false, + "green": false, + "missed_sites": 2, + "n_run": 487 + } + } +} \ No newline at end of file diff --git a/harness/tasks/e2e/deep__gin__Binding_Bind_add_validator.json b/harness/tasks/e2e/deep__gin__Binding_Bind_add_validator.json new file mode 100644 index 00000000..16ae7d85 --- /dev/null +++ b/harness/tasks/e2e/deep__gin__Binding_Bind_add_validator.json @@ -0,0 +1,1202 @@ +{ + "instance_id": "deep__gin__Binding_Bind_add_validator", + "repo": "gin-gonic/gin", + "lang": "go", + "base_commit": "d75fcd4c9ab260e5225de590f1f0f8c0e0e12d11", + "instruction": "Request bindings always validate with the package-level `binding.Validator`, so a caller cannot choose another validator per call. Make the validator explicit: add a third, required parameter `v StructValidator` to the `Bind` method of the `binding.Binding` interface (binding/binding.go and its `nomsgpack` twin binding/binding_nomsgpack.go), so it becomes `Bind(req *http.Request, obj any, v StructValidator) error`. Change every implementation (jsonBinding, xmlBinding, formBinding, formPostBinding, formMultipartBinding, queryBinding, headerBinding, plainBinding, protobufBinding, msgpackBinding, yamlBinding, tomlBinding, bsonBinding, and any implementation in tests) and every call of `Binding.Bind`, in source and in tests (including tests built only with the `nomsgpack` tag). Every existing call must pass the package-level validator, so behavior does not change: `binding.Validator` outside package binding (e.g. `Context.ShouldBindWith`), `Validator` inside it. Implementations do not have to use the new parameter yet. Do not add a two-argument variant. Do not change `Context.Bind(obj)`, the `gin.Bind` helper, `BindingBody.BindBody`, `BindingUri.BindUri` or any other `Bind*` method.", + "shapes": [ + { + "id": "Bind/2", + "name": "Bind", + "arity": 2 + } + ], + "source": "seeded", + "site_mode": "shapes", + "gold_tool": "build_deep.py go recipe: declarations by pattern (func (recv) Bind(req *http.Request, obj any) and the interface lines), call sites from go build/go test compile errors (-gcflags=-e, default tags and -tags nomsgpack), iterated to a clean build; gofmt (go1.25.14 GOTOOLCHAIN=local)", + "change": "add required parameter (interface method: 13 implementations + callers, two build-tag variants)", + "notes": "Look-alikes: Context.Bind(obj), gin.Bind(val) (arity 1), BindBody/BindUri (other names).", + "kind": "wide", + "patch": "diff --git a/binding/binding.go b/binding/binding.go\nindex eced0ae..2eea715 100644\n--- a/binding/binding.go\n+++ b/binding/binding.go\n@@ -31,7 +31,7 @@ const (\n // the form POST.\n type Binding interface {\n \tName() string\n-\tBind(*http.Request, any) error\n+\tBind(*http.Request, any, StructValidator) error\n }\n \n // BindingBody adds BindBody method to Binding. BindBody is similar with Bind,\ndiff --git a/binding/binding_msgpack_test.go b/binding/binding_msgpack_test.go\nindex 7a5db34..1e3dd69 100644\n--- a/binding/binding_msgpack_test.go\n+++ b/binding/binding_msgpack_test.go\n@@ -42,14 +42,14 @@ func testMsgPackBodyBinding(t *testing.T, b Binding, name, path, badPath, body,\n \tobj := FooStruct{}\n \treq := requestWithBody(http.MethodPost, path, body)\n \treq.Header.Add(\"Content-Type\", MIMEMSGPACK)\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.Equal(t, \"bar\", obj.Foo)\n \n \tobj = FooStruct{}\n \treq = requestWithBody(http.MethodPost, badPath, badBody)\n \treq.Header.Add(\"Content-Type\", MIMEMSGPACK)\n-\terr = MsgPack.Bind(req, &obj)\n+\terr = MsgPack.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \ndiff --git a/binding/binding_nomsgpack.go b/binding/binding_nomsgpack.go\nindex ae364d7..4291cf5 100644\n--- a/binding/binding_nomsgpack.go\n+++ b/binding/binding_nomsgpack.go\n@@ -29,7 +29,7 @@ const (\n // the form POST.\n type Binding interface {\n \tName() string\n-\tBind(*http.Request, any) error\n+\tBind(*http.Request, any, StructValidator) error\n }\n \n // BindingBody adds BindBody method to Binding. BindBody is similar with Bind,\n@@ -71,18 +71,18 @@ var Validator StructValidator = &defaultValidator{}\n // These implement the Binding interface and can be used to bind the data\n // present in the request to struct instances.\n var (\n-\tJSON = jsonBinding{}\n-\tXML = xmlBinding{}\n-\tForm = formBinding{}\n-\tQuery = queryBinding{}\n-\tFormPost = formPostBinding{}\n-\tFormMultipart = formMultipartBinding{}\n-\tProtoBuf = protobufBinding{}\n-\tYAML = yamlBinding{}\n-\tUri = uriBinding{}\n-\tHeader = headerBinding{}\n-\tTOML = tomlBinding{}\n-\tPlain = plainBinding{}\n+\tJSON = jsonBinding{}\n+\tXML = xmlBinding{}\n+\tForm = formBinding{}\n+\tQuery = queryBinding{}\n+\tFormPost = formPostBinding{}\n+\tFormMultipart = formMultipartBinding{}\n+\tProtoBuf = protobufBinding{}\n+\tYAML = yamlBinding{}\n+\tUri = uriBinding{}\n+\tHeader = headerBinding{}\n+\tTOML = tomlBinding{}\n+\tPlain = plainBinding{}\n \tBSON BindingBody = bsonBinding{}\n )\n \ndiff --git a/binding/binding_test.go b/binding/binding_test.go\nindex f90488c..04593d1 100644\n--- a/binding/binding_test.go\n+++ b/binding/binding_test.go\n@@ -181,7 +181,7 @@ func TestBindingDefault(t *testing.T) {\n func TestBindingJSONNilBody(t *testing.T) {\n \tvar obj FooStruct\n \treq, _ := http.NewRequest(http.MethodPost, \"/\", nil)\n-\terr := JSON.Bind(req, &obj)\n+\terr := JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -382,7 +382,7 @@ func TestBindingFormStringSliceMap(t *testing.T) {\n \tobj := make(map[string][]string)\n \treq := requestWithBody(http.MethodPost, \"/\", \"foo=something&foo=bar&hello=world\")\n \treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n-\terr := Form.Bind(req, &obj)\n+\terr := Form.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.NotNil(t, obj)\n \tassert.Len(t, obj, 2)\n@@ -395,7 +395,7 @@ func TestBindingFormStringSliceMap(t *testing.T) {\n \tobjInvalid := make(map[string][]int)\n \treq = requestWithBody(http.MethodPost, \"/\", \"foo=something&foo=bar&hello=world\")\n \treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n-\terr = Form.Bind(req, &objInvalid)\n+\terr = Form.Bind(req, &objInvalid, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -434,7 +434,7 @@ func TestBindingQueryStringMap(t *testing.T) {\n \n \tobj := make(map[string]string)\n \treq := requestWithBody(http.MethodGet, \"/?foo=bar&hello=world\", \"\")\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.NotNil(t, obj)\n \tassert.Len(t, obj, 2)\n@@ -443,7 +443,7 @@ func TestBindingQueryStringMap(t *testing.T) {\n \n \tobj = make(map[string]string)\n \treq = requestWithBody(http.MethodGet, \"/?foo=bar&foo=2&hello=world\", \"\") // should pick last\n-\terr = b.Bind(req, &obj)\n+\terr = b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.NotNil(t, obj)\n \tassert.Len(t, obj, 2)\n@@ -624,7 +624,7 @@ func createFormMultipartRequestForMapFail(t *testing.T) *http.Request {\n func TestBindingFormPost(t *testing.T) {\n \treq := createFormPostRequest(t)\n \tvar obj FooBarStruct\n-\trequire.NoError(t, FormPost.Bind(req, &obj))\n+\trequire.NoError(t, FormPost.Bind(req, &obj, Validator))\n \n \tassert.Equal(t, \"form-urlencoded\", FormPost.Name())\n \tassert.Equal(t, \"bar\", obj.Foo)\n@@ -634,7 +634,7 @@ func TestBindingFormPost(t *testing.T) {\n func TestBindingDefaultValueFormPost(t *testing.T) {\n \treq := createDefaultFormPostRequest(t)\n \tvar obj FooDefaultBarStruct\n-\trequire.NoError(t, FormPost.Bind(req, &obj))\n+\trequire.NoError(t, FormPost.Bind(req, &obj, Validator))\n \n \tassert.Equal(t, \"bar\", obj.Foo)\n \tassert.Equal(t, \"hello\", obj.Bar)\n@@ -643,7 +643,7 @@ func TestBindingDefaultValueFormPost(t *testing.T) {\n func TestBindingFormPostForMap(t *testing.T) {\n \treq := createFormPostRequestForMap(t)\n \tvar obj FooStructForMapType\n-\terr := FormPost.Bind(req, &obj)\n+\terr := FormPost.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.InDelta(t, float64(123), obj.MapFoo[\"bar\"].(float64), 0.01)\n }\n@@ -651,14 +651,14 @@ func TestBindingFormPostForMap(t *testing.T) {\n func TestBindingFormPostForMapFail(t *testing.T) {\n \treq := createFormPostRequestForMapFail(t)\n \tvar obj FooStructForMapType\n-\terr := FormPost.Bind(req, &obj)\n+\terr := FormPost.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n func TestBindingFormFilesMultipart(t *testing.T) {\n \treq := createFormFilesMultipartRequest(t)\n \tvar obj FooBarFileStruct\n-\terr := FormMultipart.Bind(req, &obj)\n+\terr := FormMultipart.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \n \t// file from os\n@@ -680,14 +680,14 @@ func TestBindingFormFilesMultipart(t *testing.T) {\n func TestBindingFormFilesMultipartFail(t *testing.T) {\n \treq := createFormFilesMultipartRequestFail(t)\n \tvar obj FooBarFileFailStruct\n-\terr := FormMultipart.Bind(req, &obj)\n+\terr := FormMultipart.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n func TestBindingFormMultipart(t *testing.T) {\n \treq := createFormMultipartRequest(t)\n \tvar obj FooBarStruct\n-\trequire.NoError(t, FormMultipart.Bind(req, &obj))\n+\trequire.NoError(t, FormMultipart.Bind(req, &obj, Validator))\n \n \tassert.Equal(t, \"multipart/form-data\", FormMultipart.Name())\n \tassert.Equal(t, \"bar\", obj.Foo)\n@@ -697,7 +697,7 @@ func TestBindingFormMultipart(t *testing.T) {\n func TestBindingFormMultipartForMap(t *testing.T) {\n \treq := createFormMultipartRequestForMap(t)\n \tvar obj FooStructForMapType\n-\terr := FormMultipart.Bind(req, &obj)\n+\terr := FormMultipart.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.InDelta(t, float64(123), obj.MapFoo[\"bar\"].(float64), 0.01)\n \tassert.Equal(t, \"thinkerou\", obj.MapFoo[\"name\"].(string))\n@@ -707,7 +707,7 @@ func TestBindingFormMultipartForMap(t *testing.T) {\n func TestBindingFormMultipartForMapFail(t *testing.T) {\n \treq := createFormMultipartRequestForMapFail(t)\n \tvar obj FooStructForMapType\n-\terr := FormMultipart.Bind(req, &obj)\n+\terr := FormMultipart.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -750,7 +750,7 @@ func TestBindingBSON(t *testing.T) {\n func TestValidationFails(t *testing.T) {\n \tvar obj FooStruct\n \treq := requestWithBody(http.MethodPost, \"/\", `{\"bar\": \"foo\"}`)\n-\terr := JSON.Bind(req, &obj)\n+\terr := JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -761,7 +761,7 @@ func TestValidationDisabled(t *testing.T) {\n \n \tvar obj FooStruct\n \treq := requestWithBody(http.MethodPost, \"/\", `{\"bar\": \"foo\"}`)\n-\terr := JSON.Bind(req, &obj)\n+\terr := JSON.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n }\n \n@@ -772,7 +772,7 @@ func TestRequiredSucceeds(t *testing.T) {\n \n \tvar obj HogeStruct\n \treq := requestWithBody(http.MethodPost, \"/\", `{\"hoge\": 0}`)\n-\terr := JSON.Bind(req, &obj)\n+\terr := JSON.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n }\n \n@@ -783,7 +783,7 @@ func TestRequiredFails(t *testing.T) {\n \n \tvar obj HogeStruct\n \treq := requestWithBody(http.MethodPost, \"/\", `{\"boen\": 0}`)\n-\terr := JSON.Bind(req, &obj)\n+\terr := JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -798,7 +798,7 @@ func TestHeaderBinding(t *testing.T) {\n \tvar theader tHeader\n \treq := requestWithBody(http.MethodGet, \"/\", \"\")\n \treq.Header.Add(\"limit\", \"1000\")\n-\trequire.NoError(t, h.Bind(req, &theader))\n+\trequire.NoError(t, h.Bind(req, &theader, Validator))\n \tassert.Equal(t, 1000, theader.Limit)\n \n \treq = requestWithBody(http.MethodGet, \"/\", \"\")\n@@ -808,7 +808,7 @@ func TestHeaderBinding(t *testing.T) {\n \t\tFail map[string]any `header:\"fail\"`\n \t}\n \n-\terr := h.Bind(req, &failStruct{})\n+\terr := h.Bind(req, &failStruct{}, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -864,7 +864,7 @@ func testFormBindingEmbeddedStruct(t *testing.T, method, path, badPath, body, ba\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.Equal(t, 1, obj.Page)\n \tassert.Equal(t, 2, obj.Size)\n@@ -880,14 +880,14 @@ func testFormBinding(t *testing.T, method, path, badPath, body, badBody string)\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.Equal(t, \"bar\", obj.Foo)\n \tassert.Equal(t, \"foo\", obj.Bar)\n \n \tobj = FooBarStruct{}\n \treq = requestWithBody(method, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -900,14 +900,14 @@ func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badB\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.Equal(t, \"bar\", obj.Foo)\n \tassert.Equal(t, \"hello\", obj.Bar)\n \n \tobj = FooDefaultBarStruct{}\n \treq = requestWithBody(method, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -917,7 +917,7 @@ func TestFormBindingFail(t *testing.T) {\n \n \tobj := FooBarStruct{}\n \treq, _ := http.NewRequest(http.MethodPost, \"/\", nil)\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -928,7 +928,7 @@ func TestFormBindingMultipartFail(t *testing.T) {\n \treq.Header.Set(\"Content-Type\", MIMEMultipartPOSTForm+\";boundary=testboundary\")\n \t_, err = req.MultipartReader()\n \trequire.NoError(t, err)\n-\terr = Form.Bind(req, &obj)\n+\terr = Form.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -938,7 +938,7 @@ func TestFormPostBindingFail(t *testing.T) {\n \n \tobj := FooBarStruct{}\n \treq, _ := http.NewRequest(http.MethodPost, \"/\", nil)\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -948,7 +948,7 @@ func TestFormMultipartBindingFail(t *testing.T) {\n \n \tobj := FooBarStruct{}\n \treq, _ := http.NewRequest(http.MethodPost, \"/\", nil)\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -961,7 +961,7 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \n \trequire.NoError(t, err)\n \tassert.Equal(t, int64(1510675200), obj.TimeFoo.Unix())\n@@ -975,7 +975,7 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s\n \n \tobj = FooBarStructForTimeType{}\n \treq = requestWithBody(method, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -988,12 +988,12 @@ func testFormBindingForTimeNotUnixFormat(t *testing.T, method, path, badPath, bo\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n \n \tobj = FooStructForTimeTypeNotUnixFormat{}\n \treq = requestWithBody(method, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1006,12 +1006,12 @@ func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body,\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n \n \tobj = FooStructForTimeTypeNotFormat{}\n \treq = requestWithBody(method, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1024,12 +1024,12 @@ func testFormBindingForTimeFailFormat(t *testing.T, method, path, badPath, body,\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n \n \tobj = FooStructForTimeTypeFailFormat{}\n \treq = requestWithBody(method, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1042,12 +1042,12 @@ func testFormBindingForTimeFailLocation(t *testing.T, method, path, badPath, bod\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n \n \tobj = FooStructForTimeTypeFailLocation{}\n \treq = requestWithBody(method, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1060,7 +1060,7 @@ func testFormBindingIgnoreField(t *testing.T, method, path, badPath, body, badBo\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \n \tassert.Nil(t, obj.Foo)\n@@ -1075,13 +1075,13 @@ func testFormBindingInvalidName(t *testing.T, method, path, badPath, body, badBo\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.Empty(t, obj.TestName)\n \n \tobj = InvalidNameType{}\n \treq = requestWithBody(method, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1094,12 +1094,12 @@ func testFormBindingInvalidName2(t *testing.T, method, path, badPath, body, badB\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n \n \tobj = InvalidNameMapType{}\n \treq = requestWithBody(method, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1114,17 +1114,17 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s\n \tswitch typ {\n \tcase \"Slice\":\n \t\tobj := FooStructForSliceType{}\n-\t\terr := b.Bind(req, &obj)\n+\t\terr := b.Bind(req, &obj, Validator)\n \t\trequire.NoError(t, err)\n \t\tassert.Equal(t, []int{1, 2}, obj.SliceFoo)\n \n \t\tobj = FooStructForSliceType{}\n \t\treq = requestWithBody(method, badPath, badBody)\n-\t\terr = JSON.Bind(req, &obj)\n+\t\terr = JSON.Bind(req, &obj, Validator)\n \t\trequire.Error(t, err)\n \tcase \"Struct\":\n \t\tobj := FooStructForStructType{}\n-\t\terr := b.Bind(req, &obj)\n+\t\terr := b.Bind(req, &obj, Validator)\n \t\trequire.NoError(t, err)\n \t\tassert.Equal(t,\n \t\t\tstruct {\n@@ -1133,7 +1133,7 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s\n \t\t\tobj.StructFoo)\n \tcase \"StructPointer\":\n \t\tobj := FooStructForStructPointerType{}\n-\t\terr := b.Bind(req, &obj)\n+\t\terr := b.Bind(req, &obj, Validator)\n \t\trequire.NoError(t, err)\n \t\tassert.Equal(t,\n \t\t\tstruct {\n@@ -1142,33 +1142,33 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s\n \t\t\t*obj.StructPointerFoo)\n \tcase \"Map\":\n \t\tobj := FooStructForMapType{}\n-\t\terr := b.Bind(req, &obj)\n+\t\terr := b.Bind(req, &obj, Validator)\n \t\trequire.NoError(t, err)\n \t\tassert.InDelta(t, float64(123), obj.MapFoo[\"bar\"].(float64), 0.01)\n \tcase \"SliceMap\":\n \t\tobj := FooStructForSliceMapType{}\n-\t\terr := b.Bind(req, &obj)\n+\t\terr := b.Bind(req, &obj, Validator)\n \t\trequire.Error(t, err)\n \tcase \"Ptr\":\n \t\tobj := FooStructForStringPtrType{}\n-\t\terr := b.Bind(req, &obj)\n+\t\terr := b.Bind(req, &obj, Validator)\n \t\trequire.NoError(t, err)\n \t\tassert.Nil(t, obj.PtrFoo)\n \t\tassert.Equal(t, \"test\", *obj.PtrBar)\n \n \t\tobj = FooStructForStringPtrType{}\n \t\tobj.PtrBar = new(string)\n-\t\terr = b.Bind(req, &obj)\n+\t\terr = b.Bind(req, &obj, Validator)\n \t\trequire.NoError(t, err)\n \t\tassert.Equal(t, \"test\", *obj.PtrBar)\n \n \t\tobjErr := FooStructForMapPtrType{}\n-\t\terr = b.Bind(req, &objErr)\n+\t\terr = b.Bind(req, &objErr, Validator)\n \t\trequire.Error(t, err)\n \n \t\tobj = FooStructForStringPtrType{}\n \t\treq = requestWithBody(method, badPath, badBody)\n-\t\terr = b.Bind(req, &obj)\n+\t\terr = b.Bind(req, &obj, Validator)\n \t\trequire.Error(t, err)\n \t}\n }\n@@ -1182,7 +1182,7 @@ func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string)\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.Equal(t, \"bar\", obj.Foo)\n \tassert.Equal(t, \"foo\", obj.Bar)\n@@ -1197,7 +1197,7 @@ func testQueryBindingFail(t *testing.T, method, path, badPath, body, badBody str\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1210,7 +1210,7 @@ func testQueryBindingBoolFail(t *testing.T, method, path, badPath, body, badBody\n \tif method == http.MethodPost {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1219,13 +1219,13 @@ func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody\n \n \tobj := FooStruct{}\n \treq := requestWithBody(http.MethodPost, path, body)\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.Equal(t, \"bar\", obj.Foo)\n \n \tobj = FooStruct{}\n \treq = requestWithBody(http.MethodPost, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1234,12 +1234,12 @@ func testBodyBindingSlice(t *testing.T, b Binding, name, path, badPath, body, ba\n \n \tvar obj1 []FooStruct\n \treq := requestWithBody(http.MethodPost, path, body)\n-\terr := b.Bind(req, &obj1)\n+\terr := b.Bind(req, &obj1, Validator)\n \trequire.NoError(t, err)\n \n \tvar obj2 []FooStruct\n \treq = requestWithBody(http.MethodPost, badPath, badBody)\n-\terr = JSON.Bind(req, &obj2)\n+\terr = JSON.Bind(req, &obj2, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1249,7 +1249,7 @@ func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badB\n \tif b.Name() == \"form\" {\n \t\treq.Header.Add(\"Content-Type\", MIMEPOSTForm)\n \t}\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.NotNil(t, obj)\n \tassert.Len(t, obj, 2)\n@@ -1259,13 +1259,13 @@ func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badB\n \tif badPath != \"\" && badBody != \"\" {\n \t\tobj = make(map[string]string)\n \t\treq = requestWithBody(http.MethodPost, badPath, badBody)\n-\t\terr = b.Bind(req, &obj)\n+\t\terr = b.Bind(req, &obj, Validator)\n \t\trequire.Error(t, err)\n \t}\n \n \tobjInt := make(map[string]int)\n \treq = requestWithBody(http.MethodPost, path, body)\n-\terr = b.Bind(req, &objInt)\n+\terr = b.Bind(req, &objInt, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1275,7 +1275,7 @@ func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body\n \tobj := FooStructUseNumber{}\n \treq := requestWithBody(http.MethodPost, path, body)\n \tEnableDecoderUseNumber = true\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \t// we hope it is int64(123)\n \tv, e := obj.Foo.(json.Number).Int64()\n@@ -1284,7 +1284,7 @@ func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body\n \n \tobj = FooStructUseNumber{}\n \treq = requestWithBody(http.MethodPost, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1294,7 +1294,7 @@ func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, bod\n \tobj := FooStructUseNumber{}\n \treq := requestWithBody(http.MethodPost, path, body)\n \tEnableDecoderUseNumber = false\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \t// it will return float64(123) if not use EnableDecoderUseNumber\n \t// maybe it is not hoped\n@@ -1302,7 +1302,7 @@ func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, bod\n \n \tobj = FooStructUseNumber{}\n \treq = requestWithBody(http.MethodPost, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1314,13 +1314,13 @@ func testBodyBindingDisallowUnknownFields(t *testing.T, b Binding, path, badPath\n \n \tobj := FooStructDisallowUnknownFields{}\n \treq := requestWithBody(http.MethodPost, path, body)\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.Equal(t, \"bar\", obj.Foo)\n \n \tobj = FooStructDisallowUnknownFields{}\n \treq = requestWithBody(http.MethodPost, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n \tassert.Contains(t, err.Error(), \"what\")\n }\n@@ -1330,13 +1330,13 @@ func testBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, bad\n \n \tobj := FooStruct{}\n \treq := requestWithBody(http.MethodPost, path, body)\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n \tassert.Empty(t, obj.Foo)\n \n \tobj = FooStruct{}\n \treq = requestWithBody(http.MethodPost, badPath, badBody)\n-\terr = JSON.Bind(req, &obj)\n+\terr = JSON.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1346,14 +1346,14 @@ func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, ba\n \tobj := protoexample.Test{}\n \treq := requestWithBody(http.MethodPost, path, body)\n \treq.Header.Add(\"Content-Type\", MIMEPROTOBUF)\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.NoError(t, err)\n \tassert.Equal(t, \"yes\", *obj.Label)\n \n \tobj = protoexample.Test{}\n \treq = requestWithBody(http.MethodPost, badPath, badBody)\n \treq.Header.Add(\"Content-Type\", MIMEPROTOBUF)\n-\terr = ProtoBuf.Bind(req, &obj)\n+\terr = ProtoBuf.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \n@@ -1379,28 +1379,28 @@ func TestPlainBinding(t *testing.T) {\n \n \tvar s string\n \treq := requestWithBody(http.MethodPost, \"/\", \"test string\")\n-\trequire.NoError(t, p.Bind(req, &s))\n+\trequire.NoError(t, p.Bind(req, &s, Validator))\n \tassert.Equal(t, \"test string\", s)\n \n \tvar bs []byte\n \treq = requestWithBody(http.MethodPost, \"/\", \"test []byte\")\n-\trequire.NoError(t, p.Bind(req, &bs))\n+\trequire.NoError(t, p.Bind(req, &bs, Validator))\n \tassert.Equal(t, bs, []byte(\"test []byte\"))\n \n \tvar i int\n \treq = requestWithBody(http.MethodPost, \"/\", \"test fail\")\n-\trequire.Error(t, p.Bind(req, &i))\n+\trequire.Error(t, p.Bind(req, &i, Validator))\n \n \treq = requestWithBody(http.MethodPost, \"/\", \"\")\n \treq.Body = &failRead{}\n-\trequire.Error(t, p.Bind(req, &s))\n+\trequire.Error(t, p.Bind(req, &s, Validator))\n \n \treq = requestWithBody(http.MethodPost, \"/\", \"\")\n-\trequire.NoError(t, p.Bind(req, nil))\n+\trequire.NoError(t, p.Bind(req, nil, Validator))\n \n \tvar ptr *string\n \treq = requestWithBody(http.MethodPost, \"/\", \"\")\n-\trequire.NoError(t, p.Bind(req, ptr))\n+\trequire.NoError(t, p.Bind(req, ptr, Validator))\n }\n \n func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) {\n@@ -1411,20 +1411,20 @@ func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body\n \n \treq.Body = io.NopCloser(&hook{})\n \treq.Header.Add(\"Content-Type\", MIMEPROTOBUF)\n-\terr := b.Bind(req, &obj)\n+\terr := b.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n \n \tinvalidobj := FooStruct{}\n \treq.Body = io.NopCloser(strings.NewReader(`{\"msg\":\"hello\"}`))\n \treq.Header.Add(\"Content-Type\", MIMEPROTOBUF)\n-\terr = b.Bind(req, &invalidobj)\n+\terr = b.Bind(req, &invalidobj, Validator)\n \trequire.Error(t, err)\n \tassert.Equal(t, \"obj is not ProtoMessage\", err.Error())\n \n \tobj = protoexample.Test{}\n \treq = requestWithBody(http.MethodPost, badPath, badBody)\n \treq.Header.Add(\"Content-Type\", MIMEPROTOBUF)\n-\terr = ProtoBuf.Bind(req, &obj)\n+\terr = ProtoBuf.Bind(req, &obj, Validator)\n \trequire.Error(t, err)\n }\n \ndiff --git a/binding/bson.go b/binding/bson.go\nindex 464890f..5c9eb44 100644\n--- a/binding/bson.go\n+++ b/binding/bson.go\n@@ -17,7 +17,7 @@ func (bsonBinding) Name() string {\n \treturn \"bson\"\n }\n \n-func (b bsonBinding) Bind(req *http.Request, obj any) error {\n+func (b bsonBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \tbuf, err := io.ReadAll(req.Body)\n \tif err == nil {\n \t\terr = b.BindBody(buf, obj)\ndiff --git a/binding/form.go b/binding/form.go\nindex 06732e9..0bb27dd 100644\n--- a/binding/form.go\n+++ b/binding/form.go\n@@ -21,7 +21,7 @@ func (formBinding) Name() string {\n \treturn \"form\"\n }\n \n-func (formBinding) Bind(req *http.Request, obj any) error {\n+func (formBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \tif err := req.ParseForm(); err != nil {\n \t\treturn err\n \t}\n@@ -38,7 +38,7 @@ func (formPostBinding) Name() string {\n \treturn \"form-urlencoded\"\n }\n \n-func (formPostBinding) Bind(req *http.Request, obj any) error {\n+func (formPostBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \tif err := req.ParseForm(); err != nil {\n \t\treturn err\n \t}\n@@ -52,7 +52,7 @@ func (formMultipartBinding) Name() string {\n \treturn \"multipart/form-data\"\n }\n \n-func (formMultipartBinding) Bind(req *http.Request, obj any) error {\n+func (formMultipartBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \tif err := req.ParseMultipartForm(defaultMemory); err != nil {\n \t\treturn err\n \t}\ndiff --git a/binding/header.go b/binding/header.go\nindex 6ed8c0c..4527696 100644\n--- a/binding/header.go\n+++ b/binding/header.go\n@@ -16,7 +16,7 @@ func (headerBinding) Name() string {\n \treturn \"header\"\n }\n \n-func (headerBinding) Bind(req *http.Request, obj any) error {\n+func (headerBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \tif err := mapHeader(obj, req.Header); err != nil {\n \t\treturn err\n \t}\ndiff --git a/binding/json.go b/binding/json.go\nindex f4ae921..2eabed8 100644\n--- a/binding/json.go\n+++ b/binding/json.go\n@@ -30,7 +30,7 @@ func (jsonBinding) Name() string {\n \treturn \"json\"\n }\n \n-func (jsonBinding) Bind(req *http.Request, obj any) error {\n+func (jsonBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \tif req == nil || req.Body == nil {\n \t\treturn errors.New(\"invalid request\")\n \t}\ndiff --git a/binding/msgpack.go b/binding/msgpack.go\nindex 22de9b5..9e6bea8 100644\n--- a/binding/msgpack.go\n+++ b/binding/msgpack.go\n@@ -20,7 +20,7 @@ func (msgpackBinding) Name() string {\n \treturn \"msgpack\"\n }\n \n-func (msgpackBinding) Bind(req *http.Request, obj any) error {\n+func (msgpackBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \treturn decodeMsgPack(req.Body, obj)\n }\n \ndiff --git a/binding/multipart_form_mapping_test.go b/binding/multipart_form_mapping_test.go\nindex c93f214..f949f94 100644\n--- a/binding/multipart_form_mapping_test.go\n+++ b/binding/multipart_form_mapping_test.go\n@@ -27,7 +27,7 @@ func TestFormMultipartBindingBindOneFile(t *testing.T) {\n \tfile := testFile{\"file\", \"file1\", []byte(\"hello\")}\n \n \treq := createRequestMultipartFiles(t, file)\n-\terr := FormMultipart.Bind(req, &s)\n+\terr := FormMultipart.Bind(req, &s, Validator)\n \trequire.NoError(t, err)\n \n \tassertMultipartFileHeader(t, &s.FileValue, file)\n@@ -53,7 +53,7 @@ func TestFormMultipartBindingBindTwoFiles(t *testing.T) {\n \t}\n \n \treq := createRequestMultipartFiles(t, files...)\n-\terr := FormMultipart.Bind(req, &s)\n+\terr := FormMultipart.Bind(req, &s, Validator)\n \trequire.NoError(t, err)\n \n \tassert.Len(t, s.SliceValues, len(files))\n@@ -90,7 +90,7 @@ func TestFormMultipartBindingBindError(t *testing.T) {\n \t\t}{}},\n \t} {\n \t\treq := createRequestMultipartFiles(t, files...)\n-\t\terr := FormMultipart.Bind(req, tt.s)\n+\t\terr := FormMultipart.Bind(req, tt.s, Validator)\n \t\trequire.Error(t, err)\n \t}\n }\ndiff --git a/binding/plain.go b/binding/plain.go\nindex 5d466bd..660535b 100644\n--- a/binding/plain.go\n+++ b/binding/plain.go\n@@ -15,7 +15,7 @@ func (plainBinding) Name() string {\n \treturn \"plain\"\n }\n \n-func (plainBinding) Bind(req *http.Request, obj any) error {\n+func (plainBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \tall, err := io.ReadAll(req.Body)\n \tif err != nil {\n \t\treturn err\ndiff --git a/binding/protobuf.go b/binding/protobuf.go\nindex 259ae8e..c83bbf3 100644\n--- a/binding/protobuf.go\n+++ b/binding/protobuf.go\n@@ -18,7 +18,7 @@ func (protobufBinding) Name() string {\n \treturn \"protobuf\"\n }\n \n-func (b protobufBinding) Bind(req *http.Request, obj any) error {\n+func (b protobufBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \tbuf, err := io.ReadAll(req.Body)\n \tif err != nil {\n \t\treturn err\ndiff --git a/binding/query.go b/binding/query.go\nindex c958b88..dd6a457 100644\n--- a/binding/query.go\n+++ b/binding/query.go\n@@ -12,7 +12,7 @@ func (queryBinding) Name() string {\n \treturn \"query\"\n }\n \n-func (queryBinding) Bind(req *http.Request, obj any) error {\n+func (queryBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \tvalues := req.URL.Query()\n \tif err := mapForm(obj, values); err != nil {\n \t\treturn err\ndiff --git a/binding/toml.go b/binding/toml.go\nindex 2681231..899501b 100644\n--- a/binding/toml.go\n+++ b/binding/toml.go\n@@ -18,7 +18,7 @@ func (tomlBinding) Name() string {\n \treturn \"toml\"\n }\n \n-func (tomlBinding) Bind(req *http.Request, obj any) error {\n+func (tomlBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \treturn decodeToml(req.Body, obj)\n }\n \ndiff --git a/binding/xml.go b/binding/xml.go\nindex acd6f94..d7f8bc8 100644\n--- a/binding/xml.go\n+++ b/binding/xml.go\n@@ -17,7 +17,7 @@ func (xmlBinding) Name() string {\n \treturn \"xml\"\n }\n \n-func (xmlBinding) Bind(req *http.Request, obj any) error {\n+func (xmlBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \treturn decodeXML(req.Body, obj)\n }\n \ndiff --git a/binding/yaml.go b/binding/yaml.go\nindex 6638e73..fe662fa 100644\n--- a/binding/yaml.go\n+++ b/binding/yaml.go\n@@ -18,7 +18,7 @@ func (yamlBinding) Name() string {\n \treturn \"yaml\"\n }\n \n-func (yamlBinding) Bind(req *http.Request, obj any) error {\n+func (yamlBinding) Bind(req *http.Request, obj any, v StructValidator) error {\n \treturn decodeYAML(req.Body, obj)\n }\n \ndiff --git a/context.go b/context.go\nindex a2e28e5..5f8d872 100644\n--- a/context.go\n+++ b/context.go\n@@ -917,7 +917,7 @@ func (c *Context) ShouldBindUri(obj any) error {\n // ShouldBindWith binds the passed struct pointer using the specified binding engine.\n // See the binding package.\n func (c *Context) ShouldBindWith(obj any, b binding.Binding) error {\n-\treturn b.Bind(c.Request, obj)\n+\treturn b.Bind(c.Request, obj, binding.Validator)\n }\n \n // ShouldBindBodyWith is similar with ShouldBindWith, but it stores the request\n", + "test_patch": "", + "fail_to_pass": [], + "problem_statement": "Request bindings always validate with the package-level `binding.Validator`, so a caller cannot choose another validator per call. Make the validator explicit: add a third, required parameter `v StructValidator` to the `Bind` method of the `binding.Binding` interface (binding/binding.go and its `nomsgpack` twin binding/binding_nomsgpack.go), so it becomes `Bind(req *http.Request, obj any, v StructValidator) error`. Change every implementation (jsonBinding, xmlBinding, formBinding, formPostBinding, formMultipartBinding, queryBinding, headerBinding, plainBinding, protobufBinding, msgpackBinding, yamlBinding, tomlBinding, bsonBinding, and any implementation in tests) and every call of `Binding.Bind`, in source and in tests (including tests built only with the `nomsgpack` tag). Every existing call must pass the package-level validator, so behavior does not change: `binding.Validator` outside package binding (e.g. `Context.ShouldBindWith`), `Validator` inside it. Implementations do not have to use the new parameter yet. Do not add a two-argument variant. Do not change `Context.Bind(obj)`, the `gin.Bind` helper, `BindingBody.BindBody`, `BindingUri.BindUri` or any other `Bind*` method.", + "prompt_source": "wide-mandate", + "gold_files": [ + "binding/binding.go", + "binding/binding_msgpack_test.go", + "binding/binding_nomsgpack.go", + "binding/binding_test.go", + "binding/bson.go", + "binding/form.go", + "binding/header.go", + "binding/json.go", + "binding/msgpack.go", + "binding/multipart_form_mapping_test.go", + "binding/plain.go", + "binding/protobuf.go", + "binding/query.go", + "binding/toml.go", + "binding/xml.go", + "binding/yaml.go", + "context.go" + ], + "base_shape_counts": { + "Bind/2": { + "binding/binding.go": 1, + "binding/binding_msgpack_test.go": 2, + "binding/binding_nomsgpack.go": 1, + "binding/binding_test.go": 83, + "binding/bson.go": 1, + "binding/form.go": 3, + "binding/header.go": 1, + "binding/json.go": 1, + "binding/msgpack.go": 1, + "binding/multipart_form_mapping_test.go": 3, + "binding/plain.go": 1, + "binding/protobuf.go": 1, + "binding/query.go": 1, + "binding/toml.go": 1, + "binding/xml.go": 1, + "binding/yaml.go": 1, + "context.go": 1 + } + }, + "gold_shape_counts": { + "Bind/2": {} + }, + "gold_sites": 104, + "gold_site_files": 17, + "test_functions": [ + "TestAddRoute", + "TestAddRouteFails", + "TestBadFileDescriptor", + "TestBadListener", + "TestBadTrustedCIDRs", + "TestBadTrustedCIDRsForRun", + "TestBadTrustedCIDRsForRunFd", + "TestBadTrustedCIDRsForRunListener", + "TestBadTrustedCIDRsForRunTLS", + "TestBadTrustedCIDRsForRunUnix", + "TestBadUnixSocket", + "TestBasicAuth", + "TestBasicAuth401", + "TestBasicAuth401WithCustomRealm", + "TestBasicAuthAuthorizationHeader", + "TestBasicAuthFails", + "TestBasicAuthForProxy407", + "TestBasicAuthForProxySucceed", + "TestBasicAuthSearchCredential", + "TestBasicAuthSucceed", + "TestBindMiddleware", + "TestBindUri", + "TestBindUriError", + "TestBindWith", + "TestBindingBSON", + "TestBindingDefault", + "TestBindingDefaultMsgPack", + "TestBindingDefaultValueFormPost", + "TestBindingForm", + "TestBindingForm2", + "TestBindingFormDefaultValue", + "TestBindingFormDefaultValue2", + "TestBindingFormEmbeddedStruct", + "TestBindingFormEmbeddedStruct2", + "TestBindingFormFilesMultipart", + "TestBindingFormFilesMultipartFail", + "TestBindingFormForTime", + "TestBindingFormForTime2", + "TestBindingFormForType", + "TestBindingFormInvalidName", + "TestBindingFormInvalidName2", + "TestBindingFormMultipart", + "TestBindingFormMultipartForMap", + "TestBindingFormMultipartForMapFail", + "TestBindingFormPost", + "TestBindingFormPostForMap", + "TestBindingFormPostForMapFail", + "TestBindingFormStringMap", + "TestBindingFormStringSliceMap", + "TestBindingJSON", + "TestBindingJSONDisallowUnknownFields", + "TestBindingJSONNilBody", + "TestBindingJSONSlice", + "TestBindingJSONStringMap", + "TestBindingJSONUseNumber", + "TestBindingJSONUseNumber2", + "TestBindingMsgPack", + "TestBindingProtoBuf", + "TestBindingProtoBufFail", + "TestBindingQuery", + "TestBindingQuery2", + "TestBindingQueryBoolFail", + "TestBindingQueryFail", + "TestBindingQueryFail2", + "TestBindingQueryStringMap", + "TestBindingTOML", + "TestBindingTOMLFail", + "TestBindingXML", + "TestBindingXMLFail", + "TestBindingYAML", + "TestBindingYAMLFail", + "TestBindingYAMLStringMap", + "TestCatchAllAfterSlash", + "TestChooseData", + "TestColorForLatency", + "TestColorForMethod", + "TestColorForStatus", + "TestConcurrentHandleContext", + "TestContextAbortWithError", + "TestContextAbortWithStatus", + "TestContextAbortWithStatusJSON", + "TestContextAbortWithStatusPureJSON", + "TestContextAddParam", + "TestContextAutoBindJSON", + "TestContextAutoShouldBindJSON", + "TestContextBadAutoBind", + "TestContextBadAutoShouldBind", + "TestContextBindHeader", + "TestContextBindPlain", + "TestContextBindRequestTooLarge", + "TestContextBindWithJSON", + "TestContextBindWithQuery", + "TestContextBindWithTOML", + "TestContextBindWithXML", + "TestContextBindWithYAML", + "TestContextBodyAllowedForStatus", + "TestContextClientIP", + "TestContextClientIPWithMultipleHeaders", + "TestContextClientIPWithSingleHeader", + "TestContextContentType", + "TestContextCopy", + "TestContextCopyShouldNotCancel", + "TestContextDefaultQueryOnEmptyRequest", + "TestContextError", + "TestContextFile", + "TestContextFileNotFound", + "TestContextFileSimple", + "TestContextFormFile", + "TestContextFormFileFailed", + "TestContextGetCookie", + "TestContextGetDuration", + "TestContextGetError", + "TestContextGetErrorSlice", + "TestContextGetFloat32", + "TestContextGetFloat32Slice", + "TestContextGetFloat64", + "TestContextGetFloat64Slice", + "TestContextGetInt", + "TestContextGetInt16", + "TestContextGetInt16Slice", + "TestContextGetInt32", + "TestContextGetInt32Slice", + "TestContextGetInt64", + "TestContextGetInt64Slice", + "TestContextGetInt8", + "TestContextGetInt8Slice", + "TestContextGetIntSlice", + "TestContextGetRawData", + "TestContextGetRawDataNilBody", + "TestContextGetString", + "TestContextGetStringMap", + "TestContextGetStringMapString", + "TestContextGetStringMapStringSlice", + "TestContextGetStringSlice", + "TestContextGetTime", + "TestContextGetUint", + "TestContextGetUint16", + "TestContextGetUint16Slice", + "TestContextGetUint32", + "TestContextGetUint32Slice", + "TestContextGetUint64", + "TestContextGetUint64Slice", + "TestContextGetUint8", + "TestContextGetUint8Slice", + "TestContextGetUintSlice", + "TestContextGolangContext", + "TestContextHandler", + "TestContextHandlerName", + "TestContextHandlerNames", + "TestContextHandlers", + "TestContextHeaders", + "TestContextInitQueryCache", + "TestContextIsAborted", + "TestContextMultipartForm", + "TestContextNegotiationFormat", + "TestContextNegotiationFormat2", + "TestContextNegotiationFormatCustom", + "TestContextNegotiationFormatWithAccept", + "TestContextNegotiationFormatWithWildcardAccept", + "TestContextNegotiationNotSupport", + "TestContextNegotiationWithBSON", + "TestContextNegotiationWithHTML", + "TestContextNegotiationWithJSON", + "TestContextNegotiationWithPROTOBUF", + "TestContextNegotiationWithTOML", + "TestContextNegotiationWithXML", + "TestContextNegotiationWithYAML", + "TestContextNext", + "TestContextPostFormMultipart", + "TestContextQuery", + "TestContextQueryAndPostForm", + "TestContextRenderAPIJSON", + "TestContextRenderAndEscapeAttachment", + "TestContextRenderAttachment", + "TestContextRenderData", + "TestContextRenderDataFromReader", + "TestContextRenderDataFromReaderNoHeaders", + "TestContextRenderFile", + "TestContextRenderFileFromFS", + "TestContextRenderHTML", + "TestContextRenderHTML2", + "TestContextRenderHTMLString", + "TestContextRenderIfErr", + "TestContextRenderIndentedJSON", + "TestContextRenderJSON", + "TestContextRenderJSONP", + "TestContextRenderJSONPWithoutCallback", + "TestContextRenderNoContentAPIJSON", + "TestContextRenderNoContentAsciiJSON", + "TestContextRenderNoContentData", + "TestContextRenderNoContentHTML", + "TestContextRenderNoContentHTMLString", + "TestContextRenderNoContentIndentedJSON", + "TestContextRenderNoContentJSON", + "TestContextRenderNoContentPDF", + "TestContextRenderNoContentSecureJSON", + "TestContextRenderNoContentString", + "TestContextRenderNoContentXML", + "TestContextRenderPDF", + "TestContextRenderProtoBuf", + "TestContextRenderPureJSON", + "TestContextRenderRedirectAll", + "TestContextRenderRedirectWith201", + "TestContextRenderRedirectWithAbsolutePath", + "TestContextRenderRedirectWithRelativePath", + "TestContextRenderSSE", + "TestContextRenderSecureJSON", + "TestContextRenderString", + "TestContextRenderTOML", + "TestContextRenderUTF8Attachment", + "TestContextRenderXML", + "TestContextRenderYAML", + "TestContextReset", + "TestContextResetInHandler", + "TestContextScheme", + "TestContextSetCookie", + "TestContextSetCookieData", + "TestContextSetCookiePathEmpty", + "TestContextSetGet", + "TestContextSetGetAnyKey", + "TestContextSetGetBool", + "TestContextSetGetPanicsWhenKeyNotComparable", + "TestContextSetGetValues", + "TestContextShouldBindBodyWith", + "TestContextShouldBindBodyWithJSON", + "TestContextShouldBindBodyWithPlain", + "TestContextShouldBindBodyWithTOML", + "TestContextShouldBindBodyWithXML", + "TestContextShouldBindBodyWithYAML", + "TestContextShouldBindHeader", + "TestContextShouldBindPlain", + "TestContextShouldBindWithJSON", + "TestContextShouldBindWithQuery", + "TestContextShouldBindWithTOML", + "TestContextShouldBindWithXML", + "TestContextShouldBindWithYAML", + "TestContextStream", + "TestContextStreamWithClientGone", + "TestContextTypedError", + "TestContextWithFallbackDeadlineFromRequestContext", + "TestContextWithFallbackDoneFromRequestContext", + "TestContextWithFallbackErrFromRequestContext", + "TestContextWithFallbackValueFromRequestContext", + "TestContextWithKeysMutex", + "TestCountParams", + "TestCreateDefaultRouter", + "TestCreateEngine", + "TestCreateTestContextWithRouteParams", + "TestCustomJsonCodec", + "TestCustomRecovery", + "TestCustomRecoveryWithWriter", + "TestCustomUnmarshalStruct", + "TestDebugPrint", + "TestDebugPrintError", + "TestDebugPrintFunc", + "TestDebugPrintLoadTemplate", + "TestDebugPrintRouteFunc", + "TestDebugPrintRoutes", + "TestDebugPrintWARNINGDefault", + "TestDebugPrintWARNINGDefaultWithUnsupportedVersion", + "TestDebugPrintWARNINGNew", + "TestDebugPrintWARNINGSetHTMLTemplate", + "TestDefaultLogFormatter", + "TestDefaultValidator", + "TestDir", + "TestDir_listDirectory", + "TestDisableBindValidation", + "TestDisableConsoleColor", + "TestEmptyWildcardName", + "TestEnableJsonDecoderDisallowUnknownFields", + "TestEnableJsonDecoderUseNumber", + "TestEngineHandleContext", + "TestEngineHandleContextManyReEntries", + "TestEngineHandleContextNoRouteWithEngineMiddleware", + "TestEngineHandleContextNoRouteWithGroupMiddleware", + "TestEngineHandleContextPreventsMiddlewareReEntry", + "TestEngineHandleContextUseEscapedPathOverride", + "TestEngineHandleContextUseEscapedPathPercentEncoded", + "TestEngineHandleContextUseRawPathPercentEncoded", + "TestEngineHandleMethodNotAllowedCornerCase", + "TestError", + "TestErrorLogger", + "TestErrorSlice", + "TestErrorUnwrap", + "TestEscapedColon", + "TestFileDescriptor", + "TestFilterFlags", + "TestForceConsoleColor", + "TestFormBindingFail", + "TestFormBindingIgnoreField", + "TestFormBindingMultipartFail", + "TestFormMultipartBindingBindError", + "TestFormMultipartBindingBindOneFile", + "TestFormMultipartBindingBindTwoFiles", + "TestFormMultipartBindingFail", + "TestFormPostBindingFail", + "TestFunction", + "TestFunctionName", + "TestGetMapFromFormData", + "TestGetMinVer", + "TestGetRequestHeaderValue", + "TestGithubAPI", + "TestH2c", + "TestHasRequestContext", + "TestHeaderBinding", + "TestInterceptedHeader", + "TestIsASCII", + "TestIsDebugging", + "TestIsOutputColor", + "TestJSONBindingBindBody", + "TestJSONBindingBindBodyMap", + "TestJoinPaths", + "TestLastChar", + "TestListOfRoutes", + "TestListener", + "TestLiteralColonWithDirectServeHTTP", + "TestLiteralColonWithHTTPServer", + "TestLiteralColonWithHandler", + "TestLiteralColonWithRun", + "TestLoadHTMLFSDebugMode", + "TestLoadHTMLFSFuncMap", + "TestLoadHTMLFSReleaseMode", + "TestLoadHTMLFSTestMode", + "TestLoadHTMLFSUsingTLS", + "TestLoadHTMLFilesDebugMode", + "TestLoadHTMLFilesFuncMap", + "TestLoadHTMLFilesReleaseMode", + "TestLoadHTMLFilesTestMode", + "TestLoadHTMLFilesUsingTLS", + "TestLoadHTMLGlobDebugMode", + "TestLoadHTMLGlobFromFuncMap", + "TestLoadHTMLGlobReleaseMode", + "TestLoadHTMLGlobTestMode", + "TestLoadHTMLGlobUsingTLS", + "TestLogger", + "TestLoggerWithConfig", + "TestLoggerWithConfigFormatting", + "TestLoggerWithConfigSkipQueryString", + "TestLoggerWithConfigSkipper", + "TestLoggerWithConfigSkippingPaths", + "TestLoggerWithFormatter", + "TestLoggerWithWriterSkippingPaths", + "TestMapFormWithTag", + "TestMappingArray", + "TestMappingBaseTypes", + "TestMappingCollectionFormat", + "TestMappingCollectionFormatInvalid", + "TestMappingCustomArrayForm", + "TestMappingCustomArrayOfArrayForm", + "TestMappingCustomArrayOfArrayUnmarshalTextDefault", + "TestMappingCustomArrayOfArrayUnmarshalTextForm", + "TestMappingCustomArrayOfArrayUnmarshalTextUri", + "TestMappingCustomArrayOfArrayUri", + "TestMappingCustomArrayUnmarshalTextForm", + "TestMappingCustomArrayUnmarshalTextUri", + "TestMappingCustomArrayUri", + "TestMappingCustomPointerStructTypeUnmarshalTextForm", + "TestMappingCustomPointerStructTypeUnmarshalTextUri", + "TestMappingCustomPointerStructTypeWithFormTag", + "TestMappingCustomPointerStructTypeWithURITag", + "TestMappingCustomSliceForm", + "TestMappingCustomSliceOfSliceForm", + "TestMappingCustomSliceOfSliceUnmarshalTextDefault", + "TestMappingCustomSliceOfSliceUnmarshalTextForm", + "TestMappingCustomSliceOfSliceUnmarshalTextUri", + "TestMappingCustomSliceOfSliceUri", + "TestMappingCustomSliceStopsWhenError", + "TestMappingCustomSliceUnmarshalTextForm", + "TestMappingCustomSliceUnmarshalTextStopsWhenError", + "TestMappingCustomSliceUnmarshalTextUri", + "TestMappingCustomSliceUri", + "TestMappingCustomStructTypeUnmarshalTextForm", + "TestMappingCustomStructTypeUnmarshalTextUri", + "TestMappingCustomStructTypeWithFormTag", + "TestMappingCustomStructTypeWithURITag", + "TestMappingCustomUnmarshalParamHexDefault", + "TestMappingCustomUnmarshalParamHexWithFormTag", + "TestMappingCustomUnmarshalParamHexWithURITag", + "TestMappingCustomUnmarshalTextHexDefault", + "TestMappingCustomUnmarshalTextHexForm", + "TestMappingCustomUnmarshalTextHexUri", + "TestMappingDefault", + "TestMappingEmptyValues", + "TestMappingForm", + "TestMappingFormFieldNotSent", + "TestMappingFormWithEmptyToDefault", + "TestMappingIgnoreField", + "TestMappingIgnoredCircularRef", + "TestMappingMapField", + "TestMappingMultipleDefaultWithCollectionFormat", + "TestMappingPrivateField", + "TestMappingPtrField", + "TestMappingSkipField", + "TestMappingSlice", + "TestMappingStructField", + "TestMappingTime", + "TestMappingTimeDuration", + "TestMappingTimeUnixNano", + "TestMappingURI", + "TestMappingUnexportedField", + "TestMappingUnknownFieldType", + "TestMappingUsingBindUnmarshalerAndTextUnmarshalerWhenOnlyBindUnmarshalerDefined", + "TestMappingUsingBindUnmarshalerAndTextUnmarshalerWhenOnlyTextUnmarshalerDefined", + "TestMappingUsingTextUnmarshalerWhenBindUnmarshalerAlsoDefined", + "TestMarshalXMLforH", + "TestMarshalXMLforHSuccess", + "TestMethodNotAllowedNoRoute", + "TestMiddlewareAbort", + "TestMiddlewareAbortHandlersChainAndNext", + "TestMiddlewareCalledOnceByRouterStaticFSNotFound", + "TestMiddlewareFailHandlersChain", + "TestMiddlewareGeneralCase", + "TestMiddlewareNoMethodDisabled", + "TestMiddlewareNoMethodEnabled", + "TestMiddlewareNoRoute", + "TestMiddlewareWrite", + "TestMsgpackBindingBindBody", + "TestNewOptionFunc", + "TestNoMethodWithGlobalHandlers", + "TestNoMethodWithoutGlobalHandlers", + "TestNoRouteWithGlobalHandlers", + "TestNoRouteWithoutGlobalHandlers", + "TestOnlyFilesFS_Open", + "TestOnlyFilesFS_Open_err", + "TestPanicClean", + "TestPanicInHandler", + "TestPanicWithAbort", + "TestPanicWithAbortHandler", + "TestPanicWithBrokenPipe", + "TestParseAccept", + "TestPathClean", + "TestPathCleanLong", + "TestPathCleanMallocs", + "TestPlainBinding", + "TestPrepareTrustedCIRDsWith", + "TestPusher", + "TestPusherWithPusher", + "TestPusherWithoutPusher", + "TestRaceContextCopy", + "TestRaceParamsContextCopy", + "TestReadNthLine", + "TestRebuild404Handlers", + "TestRecoveryWithWriterWithCustomRecovery", + "TestRedirectTrailingSlash", + "TestRemoteIPFail", + "TestRemoveRepeatedChar", + "TestRequiredFails", + "TestRequiredSucceeds", + "TestResetColor", + "TestResponseWriterFlush", + "TestResponseWriterHijack", + "TestResponseWriterHijackAfterWrite", + "TestResponseWriterHijackAfterWriteHeaderNow", + "TestResponseWriterReset", + "TestResponseWriterStatusCode", + "TestResponseWriterUnwrap", + "TestResponseWriterWrite", + "TestResponseWriterWriteHeader", + "TestResponseWriterWriteHeadersNow", + "TestRouteContextHoldsFullPath", + "TestRouteNotAllowedDisabled", + "TestRouteNotAllowedEnabled", + "TestRouteNotAllowedEnabled2", + "TestRouteNotAllowedEnabled3", + "TestRouteNotOK", + "TestRouteNotOK2", + "TestRouteParamsByName", + "TestRouteParamsByNameWithExtraSlash", + "TestRouteParamsNotEmpty", + "TestRouteRawPath", + "TestRouteRawPathNoUnescape", + "TestRouteRedirectFixedPath", + "TestRouteRedirectTrailingSlash", + "TestRouteServeErrorWithWriteHeader", + "TestRouteStaticFile", + "TestRouteStaticFileFS", + "TestRouteStaticListingDir", + "TestRouteStaticNoListing", + "TestRouterGroupBadMethod", + "TestRouterGroupBasic", + "TestRouterGroupBasicHandle", + "TestRouterGroupCombineHandlersEmptySliceNotNil", + "TestRouterGroupCombineHandlersTooManyHandlers", + "TestRouterGroupInvalidStatic", + "TestRouterGroupInvalidStaticFile", + "TestRouterGroupInvalidStaticFileFS", + "TestRouterGroupPipeline", + "TestRouterGroupRouteOK", + "TestRouterGroupTooManyHandlers", + "TestRouterMethod", + "TestRouterMiddlewareAndStatic", + "TestRouterNotFound", + "TestRouterNotFoundWithRemoveExtraSlash", + "TestRouterStaticFSFileNotFound", + "TestRouterStaticFSNotFound", + "TestRunEmpty", + "TestRunEmptyWithEnv", + "TestRunQUIC", + "TestRunTLS", + "TestRunTooMuchParams", + "TestRunWithPort", + "TestSafeInt8", + "TestSafeUint16", + "TestSaveUploadedCreateFailed", + "TestSaveUploadedFileWithPermission", + "TestSaveUploadedFileWithPermissionFailed", + "TestSaveUploadedOpenFailed", + "TestSecureRequestDump", + "TestSetGetDelete", + "TestSetMode", + "TestShouldBindUri", + "TestSliceValidationError", + "TestTOMLBindingBindBody", + "TestTreeAddAndGet", + "TestTreeCatchAllConflict", + "TestTreeCatchAllConflictRoot", + "TestTreeCatchMaxParams", + "TestTreeChildConflict", + "TestTreeDoubleWildcard", + "TestTreeDuplicatePath", + "TestTreeExpandParamsCapacity", + "TestTreeFindCaseInsensitivePath", + "TestTreeFindCaseInsensitivePathWildcardParamAndStaticChild", + "TestTreeFindCaseInsensitivePathWithMultipleChildrenAndWildcard", + "TestTreeInvalidEscape", + "TestTreeInvalidNodeType", + "TestTreeInvalidParamsType", + "TestTreeRootTrailingSlashRedirect", + "TestTreeRunDynamicRouting", + "TestTreeTrailingSlashRedirect", + "TestTreeWildcard", + "TestTreeWildcardConflict", + "TestTreeWildcardConflictEx", + "TestUnescapeParameters", + "TestUnixSocket", + "TestUpdateRouteTreesCalledOnce", + "TestUriBinding", + "TestUriInnerBinding", + "TestValidateAndModifyStruct", + "TestValidateNoValidationPointers", + "TestValidateNoValidationValues", + "TestValidatePrimitives", + "TestValidationDisabled", + "TestValidationFails", + "TestValidatorEngine", + "TestWebsocketsRequired", + "TestWildcardInvalidSlash", + "TestWithHttptestWithAutoSelectedPort", + "TestWithOptionFunc", + "TestWrap", + "TestXMLBindingBindBody", + "TestYAMLBindingBindBody", + "Test_neuteredReaddirFile_Readdir" + ], + "test_modules": [], + "pass_to_pass": [ + "TestAddRoute", + "TestAddRouteFails", + "TestBadFileDescriptor", + "TestBadListener", + "TestBadTrustedCIDRs", + "TestBadUnixSocket", + "TestBasicAuth", + "TestBasicAuth401", + "TestBasicAuth401WithCustomRealm", + "TestBasicAuthAuthorizationHeader", + "TestBasicAuthFails", + "TestBasicAuthForProxy407", + "TestBasicAuthForProxySucceed", + "TestBasicAuthSearchCredential", + "TestBasicAuthSucceed", + "TestBindMiddleware", + "TestBindUri", + "TestBindUriError", + "TestBindWith", + "TestBindingBSON", + "TestBindingDefault", + "TestBindingDefaultMsgPack", + "TestBindingDefaultValueFormPost", + "TestBindingForm", + "TestBindingForm2", + "TestBindingFormDefaultValue", + "TestBindingFormDefaultValue2", + "TestBindingFormEmbeddedStruct", + "TestBindingFormEmbeddedStruct2", + "TestBindingFormFilesMultipart", + "TestBindingFormFilesMultipartFail", + "TestBindingFormForTime", + "TestBindingFormForTime2", + "TestBindingFormForType", + "TestBindingFormInvalidName", + "TestBindingFormInvalidName2", + "TestBindingFormMultipart", + "TestBindingFormMultipartForMap", + "TestBindingFormMultipartForMapFail", + "TestBindingFormPost", + "TestBindingFormPostForMap", + "TestBindingFormPostForMapFail", + "TestBindingFormStringMap", + "TestBindingFormStringSliceMap", + "TestBindingJSON", + "TestBindingJSONDisallowUnknownFields", + "TestBindingJSONNilBody", + "TestBindingJSONSlice", + "TestBindingJSONStringMap", + "TestBindingJSONUseNumber", + "TestBindingJSONUseNumber2", + "TestBindingMsgPack", + "TestBindingProtoBuf", + "TestBindingProtoBufFail", + "TestBindingQuery", + "TestBindingQuery2", + "TestBindingQueryBoolFail", + "TestBindingQueryFail", + "TestBindingQueryFail2", + "TestBindingQueryStringMap", + "TestBindingTOML", + "TestBindingTOMLFail", + "TestBindingXML", + "TestBindingXMLFail", + "TestBindingYAML", + "TestBindingYAMLFail", + "TestBindingYAMLStringMap", + "TestCatchAllAfterSlash", + "TestChooseData", + "TestColorForLatency", + "TestColorForMethod", + "TestColorForStatus", + "TestConcurrentHandleContext", + "TestContextAbortWithError", + "TestContextAbortWithStatus", + "TestContextAbortWithStatusJSON", + "TestContextAbortWithStatusPureJSON", + "TestContextAddParam", + "TestContextAutoBindJSON", + "TestContextAutoShouldBindJSON", + "TestContextBadAutoBind", + "TestContextBadAutoShouldBind", + "TestContextBindHeader", + "TestContextBindPlain", + "TestContextBindRequestTooLarge", + "TestContextBindWithJSON", + "TestContextBindWithQuery", + "TestContextBindWithTOML", + "TestContextBindWithXML", + "TestContextBindWithYAML", + "TestContextBodyAllowedForStatus", + "TestContextClientIP", + "TestContextClientIPWithMultipleHeaders", + "TestContextClientIPWithSingleHeader", + "TestContextContentType", + "TestContextCopy", + "TestContextCopyShouldNotCancel", + "TestContextDefaultQueryOnEmptyRequest", + "TestContextError", + "TestContextFile", + "TestContextFileNotFound", + "TestContextFileSimple", + "TestContextFormFile", + "TestContextFormFileFailed", + "TestContextGetCookie", + "TestContextGetDuration", + "TestContextGetError", + "TestContextGetErrorSlice", + "TestContextGetFloat32", + "TestContextGetFloat32Slice", + "TestContextGetFloat64", + "TestContextGetFloat64Slice", + "TestContextGetInt", + "TestContextGetInt16", + "TestContextGetInt16Slice", + "TestContextGetInt32", + "TestContextGetInt32Slice", + "TestContextGetInt64", + "TestContextGetInt64Slice", + "TestContextGetInt8", + "TestContextGetInt8Slice", + "TestContextGetIntSlice", + "TestContextGetRawData", + "TestContextGetRawDataNilBody", + "TestContextGetString", + "TestContextGetStringMap", + "TestContextGetStringMapString", + "TestContextGetStringMapStringSlice", + "TestContextGetStringSlice", + "TestContextGetTime", + "TestContextGetUint", + "TestContextGetUint16", + "TestContextGetUint16Slice", + "TestContextGetUint32", + "TestContextGetUint32Slice", + "TestContextGetUint64", + "TestContextGetUint64Slice", + "TestContextGetUint8", + "TestContextGetUint8Slice", + "TestContextGetUintSlice", + "TestContextGolangContext", + "TestContextHandler", + "TestContextHandlerName", + "TestContextHandlerNames", + "TestContextHandlers", + "TestContextHeaders", + "TestContextInitQueryCache", + "TestContextIsAborted", + "TestContextMultipartForm", + "TestContextNegotiationFormat", + "TestContextNegotiationFormat2", + "TestContextNegotiationFormatCustom", + "TestContextNegotiationFormatWithAccept", + "TestContextNegotiationFormatWithWildcardAccept", + "TestContextNegotiationNotSupport", + "TestContextNegotiationWithBSON", + "TestContextNegotiationWithHTML", + "TestContextNegotiationWithJSON", + "TestContextNegotiationWithPROTOBUF", + "TestContextNegotiationWithTOML", + "TestContextNegotiationWithXML", + "TestContextNegotiationWithYAML", + "TestContextNext", + "TestContextPostFormMultipart", + "TestContextQuery", + "TestContextQueryAndPostForm", + "TestContextRenderAPIJSON", + "TestContextRenderAndEscapeAttachment", + "TestContextRenderAttachment", + "TestContextRenderData", + "TestContextRenderDataFromReader", + "TestContextRenderDataFromReaderNoHeaders", + "TestContextRenderFile", + "TestContextRenderFileFromFS", + "TestContextRenderHTML", + "TestContextRenderHTML2", + "TestContextRenderHTMLString", + "TestContextRenderIfErr", + "TestContextRenderIndentedJSON", + "TestContextRenderJSON", + "TestContextRenderJSONP", + "TestContextRenderJSONPWithoutCallback", + "TestContextRenderNoContentAPIJSON", + "TestContextRenderNoContentAsciiJSON", + "TestContextRenderNoContentData", + "TestContextRenderNoContentHTML", + "TestContextRenderNoContentHTMLString", + "TestContextRenderNoContentIndentedJSON", + "TestContextRenderNoContentJSON", + "TestContextRenderNoContentPDF", + "TestContextRenderNoContentSecureJSON", + "TestContextRenderNoContentString", + "TestContextRenderNoContentXML", + "TestContextRenderPDF", + "TestContextRenderProtoBuf", + "TestContextRenderPureJSON", + "TestContextRenderRedirectAll", + "TestContextRenderRedirectWith201", + "TestContextRenderRedirectWithAbsolutePath", + "TestContextRenderRedirectWithRelativePath", + "TestContextRenderSSE", + "TestContextRenderSecureJSON", + "TestContextRenderString", + "TestContextRenderTOML", + "TestContextRenderUTF8Attachment", + "TestContextRenderXML", + "TestContextRenderYAML", + "TestContextReset", + "TestContextResetInHandler", + "TestContextScheme", + "TestContextSetCookie", + "TestContextSetCookieData", + "TestContextSetCookiePathEmpty", + "TestContextSetGet", + "TestContextSetGetAnyKey", + "TestContextSetGetBool", + "TestContextSetGetPanicsWhenKeyNotComparable", + "TestContextSetGetValues", + "TestContextShouldBindBodyWith", + "TestContextShouldBindBodyWithJSON", + "TestContextShouldBindBodyWithPlain", + "TestContextShouldBindBodyWithTOML", + "TestContextShouldBindBodyWithXML", + "TestContextShouldBindBodyWithYAML", + "TestContextShouldBindHeader", + "TestContextShouldBindPlain", + "TestContextShouldBindWithJSON", + "TestContextShouldBindWithQuery", + "TestContextShouldBindWithTOML", + "TestContextShouldBindWithXML", + "TestContextShouldBindWithYAML", + "TestContextStream", + "TestContextStreamWithClientGone", + "TestContextTypedError", + "TestContextWithFallbackDeadlineFromRequestContext", + "TestContextWithFallbackDoneFromRequestContext", + "TestContextWithFallbackErrFromRequestContext", + "TestContextWithFallbackValueFromRequestContext", + "TestContextWithKeysMutex", + "TestCountParams", + "TestCreateDefaultRouter", + "TestCreateEngine", + "TestCreateTestContextWithRouteParams", + "TestCustomJsonCodec", + "TestCustomRecovery", + "TestCustomRecoveryWithWriter", + "TestCustomUnmarshalStruct", + "TestDebugPrint", + "TestDebugPrintError", + "TestDebugPrintFunc", + "TestDebugPrintLoadTemplate", + "TestDebugPrintRouteFunc", + "TestDebugPrintRoutes", + "TestDebugPrintWARNINGDefault", + "TestDebugPrintWARNINGDefaultWithUnsupportedVersion", + "TestDebugPrintWARNINGNew", + "TestDebugPrintWARNINGSetHTMLTemplate", + "TestDefaultLogFormatter", + "TestDefaultValidator", + "TestDir", + "TestDir_listDirectory", + "TestDisableBindValidation", + "TestDisableConsoleColor", + "TestEmptyWildcardName", + "TestEnableJsonDecoderDisallowUnknownFields", + "TestEnableJsonDecoderUseNumber", + "TestEngineHandleContext", + "TestEngineHandleContextManyReEntries", + "TestEngineHandleContextNoRouteWithEngineMiddleware", + "TestEngineHandleContextNoRouteWithGroupMiddleware", + "TestEngineHandleContextPreventsMiddlewareReEntry", + "TestEngineHandleContextUseEscapedPathOverride", + "TestEngineHandleContextUseEscapedPathPercentEncoded", + "TestEngineHandleContextUseRawPathPercentEncoded", + "TestEngineHandleMethodNotAllowedCornerCase", + "TestError", + "TestErrorLogger", + "TestErrorSlice", + "TestErrorUnwrap", + "TestEscapedColon", + "TestFileDescriptor", + "TestFilterFlags", + "TestForceConsoleColor", + "TestFormBindingFail", + "TestFormBindingIgnoreField", + "TestFormBindingMultipartFail", + "TestFormMultipartBindingBindError", + "TestFormMultipartBindingBindOneFile", + "TestFormMultipartBindingBindTwoFiles", + "TestFormMultipartBindingFail", + "TestFormPostBindingFail", + "TestFunction", + "TestFunctionName", + "TestGetMapFromFormData", + "TestGetMinVer", + "TestGetRequestHeaderValue", + "TestGithubAPI", + "TestH2c", + "TestHasRequestContext", + "TestHeaderBinding", + "TestInterceptedHeader", + "TestIsASCII", + "TestIsDebugging", + "TestIsOutputColor", + "TestJSONBindingBindBody", + "TestJSONBindingBindBodyMap", + "TestJoinPaths", + "TestLastChar", + "TestListOfRoutes", + "TestListener", + "TestLiteralColonWithDirectServeHTTP", + "TestLiteralColonWithHTTPServer", + "TestLiteralColonWithHandler", + "TestLiteralColonWithRun", + "TestLoadHTMLFSDebugMode", + "TestLoadHTMLFSFuncMap", + "TestLoadHTMLFSReleaseMode", + "TestLoadHTMLFSTestMode", + "TestLoadHTMLFSUsingTLS", + "TestLoadHTMLFilesDebugMode", + "TestLoadHTMLFilesFuncMap", + "TestLoadHTMLFilesReleaseMode", + "TestLoadHTMLFilesTestMode", + "TestLoadHTMLFilesUsingTLS", + "TestLoadHTMLGlobDebugMode", + "TestLoadHTMLGlobFromFuncMap", + "TestLoadHTMLGlobReleaseMode", + "TestLoadHTMLGlobTestMode", + "TestLoadHTMLGlobUsingTLS", + "TestLogger", + "TestLoggerWithConfig", + "TestLoggerWithConfigFormatting", + "TestLoggerWithConfigSkipQueryString", + "TestLoggerWithConfigSkipper", + "TestLoggerWithConfigSkippingPaths", + "TestLoggerWithFormatter", + "TestLoggerWithWriterSkippingPaths", + "TestMapFormWithTag", + "TestMappingArray", + "TestMappingBaseTypes", + "TestMappingCollectionFormat", + "TestMappingCollectionFormatInvalid", + "TestMappingCustomArrayForm", + "TestMappingCustomArrayOfArrayForm", + "TestMappingCustomArrayOfArrayUnmarshalTextDefault", + "TestMappingCustomArrayOfArrayUnmarshalTextForm", + "TestMappingCustomArrayOfArrayUnmarshalTextUri", + "TestMappingCustomArrayOfArrayUri", + "TestMappingCustomArrayUnmarshalTextForm", + "TestMappingCustomArrayUnmarshalTextUri", + "TestMappingCustomArrayUri", + "TestMappingCustomPointerStructTypeUnmarshalTextForm", + "TestMappingCustomPointerStructTypeUnmarshalTextUri", + "TestMappingCustomPointerStructTypeWithFormTag", + "TestMappingCustomPointerStructTypeWithURITag", + "TestMappingCustomSliceForm", + "TestMappingCustomSliceOfSliceForm", + "TestMappingCustomSliceOfSliceUnmarshalTextDefault", + "TestMappingCustomSliceOfSliceUnmarshalTextForm", + "TestMappingCustomSliceOfSliceUnmarshalTextUri", + "TestMappingCustomSliceOfSliceUri", + "TestMappingCustomSliceStopsWhenError", + "TestMappingCustomSliceUnmarshalTextForm", + "TestMappingCustomSliceUnmarshalTextStopsWhenError", + "TestMappingCustomSliceUnmarshalTextUri", + "TestMappingCustomSliceUri", + "TestMappingCustomStructTypeUnmarshalTextForm", + "TestMappingCustomStructTypeUnmarshalTextUri", + "TestMappingCustomStructTypeWithFormTag", + "TestMappingCustomStructTypeWithURITag", + "TestMappingCustomUnmarshalParamHexDefault", + "TestMappingCustomUnmarshalParamHexWithFormTag", + "TestMappingCustomUnmarshalParamHexWithURITag", + "TestMappingCustomUnmarshalTextHexDefault", + "TestMappingCustomUnmarshalTextHexForm", + "TestMappingCustomUnmarshalTextHexUri", + "TestMappingDefault", + "TestMappingEmptyValues", + "TestMappingForm", + "TestMappingFormFieldNotSent", + "TestMappingFormWithEmptyToDefault", + "TestMappingIgnoreField", + "TestMappingIgnoredCircularRef", + "TestMappingMapField", + "TestMappingMultipleDefaultWithCollectionFormat", + "TestMappingPrivateField", + "TestMappingPtrField", + "TestMappingSkipField", + "TestMappingSlice", + "TestMappingStructField", + "TestMappingTime", + "TestMappingTimeDuration", + "TestMappingTimeUnixNano", + "TestMappingURI", + "TestMappingUnexportedField", + "TestMappingUnknownFieldType", + "TestMappingUsingBindUnmarshalerAndTextUnmarshalerWhenOnlyBindUnmarshalerDefined", + "TestMappingUsingBindUnmarshalerAndTextUnmarshalerWhenOnlyTextUnmarshalerDefined", + "TestMappingUsingTextUnmarshalerWhenBindUnmarshalerAlsoDefined", + "TestMarshalXMLforH", + "TestMarshalXMLforHSuccess", + "TestMethodNotAllowedNoRoute", + "TestMiddlewareAbort", + "TestMiddlewareAbortHandlersChainAndNext", + "TestMiddlewareCalledOnceByRouterStaticFSNotFound", + "TestMiddlewareFailHandlersChain", + "TestMiddlewareGeneralCase", + "TestMiddlewareNoMethodDisabled", + "TestMiddlewareNoMethodEnabled", + "TestMiddlewareNoRoute", + "TestMiddlewareWrite", + "TestMsgpackBindingBindBody", + "TestNewOptionFunc", + "TestNoMethodWithGlobalHandlers", + "TestNoMethodWithoutGlobalHandlers", + "TestNoRouteWithGlobalHandlers", + "TestNoRouteWithoutGlobalHandlers", + "TestOnlyFilesFS_Open", + "TestOnlyFilesFS_Open_err", + "TestPanicClean", + "TestPanicInHandler", + "TestPanicWithAbort", + "TestPanicWithAbortHandler", + "TestPanicWithBrokenPipe", + "TestParseAccept", + "TestPathClean", + "TestPathCleanLong", + "TestPlainBinding", + "TestPrepareTrustedCIRDsWith", + "TestPusher", + "TestPusherWithPusher", + "TestPusherWithoutPusher", + "TestRaceContextCopy", + "TestRaceParamsContextCopy", + "TestReadNthLine", + "TestRebuild404Handlers", + "TestRecoveryWithWriterWithCustomRecovery", + "TestRedirectTrailingSlash", + "TestRemoteIPFail", + "TestRemoveRepeatedChar", + "TestRequiredFails", + "TestRequiredSucceeds", + "TestResetColor", + "TestResponseWriterFlush", + "TestResponseWriterHijack", + "TestResponseWriterHijackAfterWrite", + "TestResponseWriterHijackAfterWriteHeaderNow", + "TestResponseWriterReset", + "TestResponseWriterStatusCode", + "TestResponseWriterUnwrap", + "TestResponseWriterWrite", + "TestResponseWriterWriteHeader", + "TestResponseWriterWriteHeadersNow", + "TestRouteContextHoldsFullPath", + "TestRouteNotAllowedDisabled", + "TestRouteNotAllowedEnabled", + "TestRouteNotAllowedEnabled2", + "TestRouteNotAllowedEnabled3", + "TestRouteNotOK", + "TestRouteNotOK2", + "TestRouteParamsByName", + "TestRouteParamsByNameWithExtraSlash", + "TestRouteParamsNotEmpty", + "TestRouteRawPath", + "TestRouteRawPathNoUnescape", + "TestRouteRedirectFixedPath", + "TestRouteRedirectTrailingSlash", + "TestRouteServeErrorWithWriteHeader", + "TestRouteStaticFile", + "TestRouteStaticFileFS", + "TestRouteStaticListingDir", + "TestRouteStaticNoListing", + "TestRouterGroupBadMethod", + "TestRouterGroupBasic", + "TestRouterGroupBasicHandle", + "TestRouterGroupCombineHandlersEmptySliceNotNil", + "TestRouterGroupCombineHandlersTooManyHandlers", + "TestRouterGroupInvalidStatic", + "TestRouterGroupInvalidStaticFile", + "TestRouterGroupInvalidStaticFileFS", + "TestRouterGroupPipeline", + "TestRouterGroupRouteOK", + "TestRouterGroupTooManyHandlers", + "TestRouterMethod", + "TestRouterMiddlewareAndStatic", + "TestRouterNotFound", + "TestRouterNotFoundWithRemoveExtraSlash", + "TestRouterStaticFSFileNotFound", + "TestRouterStaticFSNotFound", + "TestRunEmpty", + "TestRunEmptyWithEnv", + "TestRunQUIC", + "TestRunTLS", + "TestRunTooMuchParams", + "TestRunWithPort", + "TestSafeInt8", + "TestSafeUint16", + "TestSaveUploadedCreateFailed", + "TestSaveUploadedFileWithPermission", + "TestSaveUploadedFileWithPermissionFailed", + "TestSaveUploadedOpenFailed", + "TestSecureRequestDump", + "TestSetGetDelete", + "TestSetMode", + "TestShouldBindUri", + "TestSliceValidationError", + "TestTOMLBindingBindBody", + "TestTreeAddAndGet", + "TestTreeCatchAllConflict", + "TestTreeCatchAllConflictRoot", + "TestTreeCatchMaxParams", + "TestTreeChildConflict", + "TestTreeDoubleWildcard", + "TestTreeDuplicatePath", + "TestTreeExpandParamsCapacity", + "TestTreeFindCaseInsensitivePath", + "TestTreeFindCaseInsensitivePathWildcardParamAndStaticChild", + "TestTreeFindCaseInsensitivePathWithMultipleChildrenAndWildcard", + "TestTreeInvalidEscape", + "TestTreeInvalidNodeType", + "TestTreeInvalidParamsType", + "TestTreeRootTrailingSlashRedirect", + "TestTreeRunDynamicRouting", + "TestTreeTrailingSlashRedirect", + "TestTreeWildcard", + "TestTreeWildcardConflict", + "TestTreeWildcardConflictEx", + "TestUnescapeParameters", + "TestUnixSocket", + "TestUpdateRouteTreesCalledOnce", + "TestUriBinding", + "TestUriInnerBinding", + "TestValidateAndModifyStruct", + "TestValidateNoValidationPointers", + "TestValidateNoValidationValues", + "TestValidatePrimitives", + "TestValidationDisabled", + "TestValidationFails", + "TestValidatorEngine", + "TestWebsocketsRequired", + "TestWildcardInvalidSlash", + "TestWithHttptestWithAutoSelectedPort", + "TestWithOptionFunc", + "TestWrap", + "TestXMLBindingBindBody", + "TestYAMLBindingBindBody", + "Test_neuteredReaddirFile_Readdir" + ], + "gold_test_outcomes": { + "run": 548, + "passed": 547, + "failed": [ + "TestPathCleanMallocs" + ] + }, + "validation": { + "gold": { + "resolved": true, + "sites_ok": true, + "green": true, + "n_run": 548 + }, + "empty": { + "resolved": false, + "sites_ok": false, + "missed_sites": 104 + }, + "partial": { + "resolved": false, + "sites_ok": false, + "green": false, + "missed_sites": 4, + "n_run": 408 + } + } +} \ No newline at end of file diff --git a/harness/tasks/e2e/deep__gson__TypeAdapterFactory_create_Optional.json b/harness/tasks/e2e/deep__gson__TypeAdapterFactory_create_Optional.json new file mode 100644 index 00000000..cd3fb327 --- /dev/null +++ b/harness/tasks/e2e/deep__gson__TypeAdapterFactory_create_Optional.json @@ -0,0 +1,276 @@ +{ + "instance_id": "deep__gson__TypeAdapterFactory_create_Optional", + "repo": "google/gson", + "lang": "java", + "base_commit": "dae37cf0fe12235b76fb09f01118a0a8c8823f42", + "instruction": "`TypeAdapterFactory.create(Gson gson, TypeToken type)` (com.google.gson) signals \"this factory does not handle the type\" by returning `null`, which every caller has to remember to check. Change its return type to `java.util.Optional>`: a factory that does not handle the type returns `Optional.empty()`, a factory that does returns the adapter wrapped in an `Optional` (use `Optional.ofNullable` where the adapter expression itself may be null). Update the interface and every implementation -- named classes and anonymous `new TypeAdapterFactory() { ... }` classes, in all Maven modules (gson, extras, proto, test-shrinker, ...) and in tests -- changing only the `return` statements that belong to `create` itself (not the `return null` inside a nested `TypeAdapter`'s `read`/`write`). Update every caller of `create` (e.g. `Gson.getAdapter`, `Gson.getDelegateAdapter`, `JsonAdapterAnnotationTypeAdapterFactory`, tests) to unwrap the `Optional` so that \"not handled\" is treated exactly as `null` was. Do not add a nullable-returning variant. Behavior must not change.", + "shapes": [ + { + "id": "TypeAdapter create(Gson", + "regex": "\\bTypeAdapter\\s*<\\s*\\w+\\s*>\\s+create\\s*\\(\\s*(?:final\\s+)?Gson\\b" + } + ], + "source": "seeded", + "site_mode": "shapes", + "gold_tool": "build_deep.py recipe: create() declarations and their own return statements rewritten (nested-class/lambda returns excluded by a brace scan); callers unwrapped with .orElse(null) from javac errors; docker maven test-compile clean", + "change": "change return type (nullable -> Optional) of an interface method: ~45 implementations + callers", + "notes": "", + "kind": "wide", + "patch": "diff --git a/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java b/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java\nindex 7868a133..13d4b7f2 100644\n--- a/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java\n+++ b/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java\n@@ -24,17 +24,18 @@ import com.google.gson.stream.JsonReader;\n import com.google.gson.stream.JsonWriter;\n import java.io.IOException;\n \n+import java.util.Optional;\n /** A type adapter factory that implements {@code @Intercept}. */\n public final class InterceptorFactory implements TypeAdapterFactory {\n @Override\n- public TypeAdapter create(Gson gson, TypeToken type) {\n+ public Optional> create(Gson gson, TypeToken type) {\n Intercept intercept = type.getRawType().getAnnotation(Intercept.class);\n if (intercept == null) {\n- return null;\n+ return Optional.empty();\n }\n \n TypeAdapter delegate = gson.getDelegateAdapter(this, type);\n- return new InterceptorAdapter<>(delegate, intercept);\n+ return Optional.of(new InterceptorAdapter<>(delegate, intercept));\n }\n \n static class InterceptorAdapter extends TypeAdapter {\ndiff --git a/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java b/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java\nindex 924a9089..d4adfcb9 100644\n--- a/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java\n+++ b/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java\n@@ -27,10 +27,11 @@ import java.lang.reflect.InvocationTargetException;\n import java.lang.reflect.Method;\n import javax.annotation.PostConstruct;\n \n+import java.util.Optional;\n public class PostConstructAdapterFactory implements TypeAdapterFactory {\n // copied from https://gist.github.com/swankjesse/20df26adaf639ed7fd160f145a0b661a\n @Override\n- public TypeAdapter create(Gson gson, TypeToken type) {\n+ public Optional> create(Gson gson, TypeToken type) {\n for (Class t = type.getRawType();\n (t != Object.class) && (t.getSuperclass() != null);\n t = t.getSuperclass()) {\n@@ -38,11 +39,11 @@ public class PostConstructAdapterFactory implements TypeAdapterFactory {\n if (m.isAnnotationPresent(PostConstruct.class)) {\n m.setAccessible(true);\n TypeAdapter delegate = gson.getDelegateAdapter(this, type);\n- return new PostConstructAdapter<>(delegate, m);\n+ return Optional.of(new PostConstructAdapter<>(delegate, m));\n }\n }\n }\n- return null;\n+ return Optional.empty();\n }\n \n static final class PostConstructAdapter extends TypeAdapter {\ndiff --git a/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java b/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java\nindex 01812ad2..42174b33 100644\n--- a/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java\n+++ b/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java\n@@ -31,6 +31,7 @@ import java.io.IOException;\n import java.util.LinkedHashMap;\n import java.util.Map;\n \n+import java.util.Optional;\n /**\n * Adapts values whose runtime type may differ from their declaration type. This is necessary when a\n * field's type is not the same type that GSON should create when deserializing that field. For\n@@ -241,15 +242,15 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory {\n }\n \n @Override\n- public TypeAdapter create(Gson gson, TypeToken type) {\n+ public Optional> create(Gson gson, TypeToken type) {\n if (type == null) {\n- return null;\n+ return Optional.empty();\n }\n Class rawType = type.getRawType();\n boolean handle =\n recognizeSubtypes ? baseType.isAssignableFrom(rawType) : baseType.equals(rawType);\n if (!handle) {\n- return null;\n+ return Optional.empty();\n }\n \n TypeAdapter jsonElementAdapter = gson.getAdapter(JsonElement.class);\n@@ -261,7 +262,7 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory {\n subtypeToDelegate.put(entry.getValue(), delegate);\n }\n \n- return new TypeAdapter() {\n+ return Optional.ofNullable(new TypeAdapter() {\n @Override\n public R read(JsonReader in) throws IOException {\n JsonElement jsonElement = jsonElementAdapter.read(in);\n@@ -326,6 +327,6 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory {\n }\n jsonElementAdapter.write(out, clone);\n }\n- }.nullSafe();\n+ }.nullSafe());\n }\n }\ndiff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java\nindex 28ba4ae3..c1e83b31 100644\n--- a/gson/src/main/java/com/google/gson/Gson.java\n+++ b/gson/src/main/java/com/google/gson/Gson.java\n@@ -367,7 +367,7 @@ public final class Gson {\n threadCalls.put(type, call);\n \n for (TypeAdapterFactory factory : factories) {\n- candidate = factory.create(this, type);\n+ candidate = factory.create(this, type).orElse(null);\n if (candidate != null) {\n call.setDelegate(candidate);\n // Replace future adapter with actual adapter\n@@ -488,7 +488,7 @@ public final class Gson {\n continue;\n }\n \n- TypeAdapter candidate = factory.create(this, type);\n+ TypeAdapter candidate = factory.create(this, type).orElse(null);\n if (candidate != null) {\n return candidate;\n }\ndiff --git a/gson/src/main/java/com/google/gson/TypeAdapterFactory.java b/gson/src/main/java/com/google/gson/TypeAdapterFactory.java\nindex cf40fc18..7aac8913 100644\n--- a/gson/src/main/java/com/google/gson/TypeAdapterFactory.java\n+++ b/gson/src/main/java/com/google/gson/TypeAdapterFactory.java\n@@ -18,6 +18,7 @@ package com.google.gson;\n \n import com.google.gson.reflect.TypeToken;\n \n+import java.util.Optional;\n /**\n * Creates type adapters for set of related types. Type adapter factories are most useful when\n * several types share similar structure in their JSON form.\n@@ -167,5 +168,5 @@ public interface TypeAdapterFactory {\n /**\n * Returns a type adapter for {@code type}, or null if this factory doesn't support {@code type}.\n */\n- TypeAdapter create(Gson gson, TypeToken type);\n+ Optional> create(Gson gson, TypeToken type);\n }\ndiff --git a/gson/src/main/java/com/google/gson/internal/Excluder.java b/gson/src/main/java/com/google/gson/internal/Excluder.java\nindex 632e5454..86421626 100644\n--- a/gson/src/main/java/com/google/gson/internal/Excluder.java\n+++ b/gson/src/main/java/com/google/gson/internal/Excluder.java\n@@ -35,6 +35,7 @@ import java.util.ArrayList;\n import java.util.Collections;\n import java.util.List;\n \n+import java.util.Optional;\n /**\n * This class selects which fields and types to omit. It is configurable, supporting version\n * attributes {@link Since} and {@link Until}, modifiers, synthetic fields, anonymous and local\n@@ -108,17 +109,17 @@ public final class Excluder implements TypeAdapterFactory, Cloneable {\n }\n \n @Override\n- public TypeAdapter create(Gson gson, TypeToken type) {\n+ public Optional> create(Gson gson, TypeToken type) {\n Class rawType = type.getRawType();\n \n boolean skipSerialize = excludeClass(rawType, true);\n boolean skipDeserialize = excludeClass(rawType, false);\n \n if (!skipSerialize && !skipDeserialize) {\n- return null;\n+ return Optional.empty();\n }\n \n- return new TypeAdapter() {\n+ return Optional.of(new TypeAdapter() {\n /**\n * The delegate is lazily created because it may not be needed, and creating it may fail.\n * Field has to be {@code volatile} because {@link Gson} guarantees to be thread-safe.\n@@ -152,7 +153,7 @@ public final class Excluder implements TypeAdapterFactory, Cloneable {\n }\n return d;\n }\n- };\n+ });\n }\n \n public boolean excludeField(Field field, boolean serialize) {\ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java\nindex 50efa418..239f1027 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java\n@@ -30,16 +30,17 @@ import java.lang.reflect.GenericArrayType;\n import java.lang.reflect.Type;\n import java.util.ArrayList;\n \n+import java.util.Optional;\n /** Adapter for arrays. */\n public final class ArrayTypeAdapter extends TypeAdapter {\n public static final TypeAdapterFactory FACTORY =\n new TypeAdapterFactory() {\n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n Type type = typeToken.getType();\n if (!(type instanceof GenericArrayType\n || (type instanceof Class && ((Class) type).isArray()))) {\n- return null;\n+ return Optional.empty();\n }\n \n Type componentType = GsonTypes.getArrayComponentType(type);\n@@ -48,7 +49,7 @@ public final class ArrayTypeAdapter extends TypeAdapter {\n @SuppressWarnings({\"unchecked\", \"rawtypes\"})\n TypeAdapter arrayAdapter =\n new ArrayTypeAdapter(gson, componentTypeAdapter, GsonTypes.getRawType(componentType));\n- return arrayAdapter;\n+ return Optional.ofNullable(arrayAdapter);\n }\n };\n \ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java\nindex 7dd48a3e..d5109abd 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java\n@@ -30,6 +30,7 @@ import java.io.IOException;\n import java.lang.reflect.Type;\n import java.util.Collection;\n \n+import java.util.Optional;\n /** Adapt a homogeneous collection of objects. */\n public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {\n private final ConstructorConstructor constructorConstructor;\n@@ -39,12 +40,12 @@ public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {\n }\n \n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n Type type = typeToken.getType();\n \n Class rawType = typeToken.getRawType();\n if (!Collection.class.isAssignableFrom(rawType)) {\n- return null;\n+ return Optional.empty();\n }\n \n Type elementType = GsonTypes.getCollectionElementType(type, rawType);\n@@ -58,7 +59,7 @@ public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {\n \n @SuppressWarnings({\"unchecked\", \"rawtypes\"}) // create() doesn't define a type parameter\n TypeAdapter result = new Adapter(wrappedTypeAdapter, constructor);\n- return result;\n+ return Optional.ofNullable(result);\n }\n \n private static final class Adapter extends TypeAdapter> {\ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java\nindex b5dffe24..2d412f93 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java\n@@ -39,6 +39,7 @@ import java.util.Locale;\n import java.util.Objects;\n import java.util.TimeZone;\n \n+import java.util.Optional;\n /**\n * This type adapter supports subclasses of date by defining a {@link\n * DefaultDateTypeAdapter.DateType} and then using its {@code createAdapterFactory} methods.\n@@ -65,12 +66,12 @@ public final class DefaultDateTypeAdapter extends TypeAdapter\n new TypeAdapterFactory() {\n @SuppressWarnings(\"unchecked\") // we use a runtime check to make sure the 'T's equal\n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n- return typeToken.getRawType() == Date.class\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n+ return Optional.ofNullable(typeToken.getRawType() == Date.class\n ? (TypeAdapter)\n new DefaultDateTypeAdapter<>(\n DateType.DATE, DateFormat.DEFAULT, DateFormat.DEFAULT)\n- : null;\n+ : null);\n }\n \n @Override\ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java\nindex b3dbb680..c1dd55e4 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java\n@@ -31,22 +31,23 @@ import java.util.Arrays;\n import java.util.HashMap;\n import java.util.Map;\n \n+import java.util.Optional;\n /** Adapter for enum classes (but not for the base class {@code java.lang.Enum}). */\n class EnumTypeAdapter> extends TypeAdapter {\n static final TypeAdapterFactory FACTORY =\n new TypeAdapterFactory() {\n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n Class rawType = typeToken.getRawType();\n if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) {\n- return null;\n+ return Optional.empty();\n }\n if (!rawType.isEnum()) {\n rawType = rawType.getSuperclass(); // handle anonymous subclasses\n }\n @SuppressWarnings({\"rawtypes\", \"unchecked\"})\n TypeAdapter adapter = (TypeAdapter) new EnumTypeAdapter(rawType);\n- return adapter;\n+ return Optional.ofNullable(adapter);\n }\n };\n \ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java b/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java\nindex 92fc7647..7fcb61dc 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java\n@@ -27,6 +27,7 @@ import java.time.ZoneId;\n import java.time.ZoneOffset;\n import java.time.ZonedDateTime;\n \n+import java.util.Optional;\n /**\n * Type adapters for {@code java.time} types.\n *\n@@ -393,12 +394,12 @@ final class JavaTimeTypeAdapters implements TypeAdapters.FactorySupplier {\n static final TypeAdapterFactory JAVA_TIME_FACTORY =\n new TypeAdapterFactory() {\n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n Class rawType = typeToken.getRawType();\n if (!rawType.getName().startsWith(\"java.time.\")) {\n // Immediately return null so we don't load all these classes when nobody's doing\n // anything with java.time.\n- return null;\n+ return Optional.empty();\n }\n TypeAdapter adapter = null;\n if (rawType == Duration.class) {\n@@ -435,7 +436,7 @@ final class JavaTimeTypeAdapters implements TypeAdapters.FactorySupplier {\n }\n @SuppressWarnings(\"unchecked\")\n TypeAdapter result = (TypeAdapter) adapter;\n- return result;\n+ return Optional.ofNullable(result);\n }\n };\n \ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java\nindex 6d254c8b..31d52742 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java\n@@ -28,6 +28,7 @@ import java.util.Objects;\n import java.util.concurrent.ConcurrentHashMap;\n import java.util.concurrent.ConcurrentMap;\n \n+import java.util.Optional;\n /**\n * Given a type T, looks for the annotation {@link JsonAdapter} and uses an instance of the\n * specified class as the default type adapter.\n@@ -37,7 +38,7 @@ import java.util.concurrent.ConcurrentMap;\n public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapterFactory {\n private static final class DummyTypeAdapterFactory implements TypeAdapterFactory {\n @Override\n- public TypeAdapter create(Gson gson, TypeToken type) {\n+ public Optional> create(Gson gson, TypeToken type) {\n throw new AssertionError(\"Factory should not be used\");\n }\n }\n@@ -74,14 +75,14 @@ public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapte\n // this is not safe; requires that user has specified correct adapter class for @JsonAdapter\n @SuppressWarnings(\"unchecked\")\n @Override\n- public TypeAdapter create(Gson gson, TypeToken targetType) {\n+ public Optional> create(Gson gson, TypeToken targetType) {\n Class rawType = targetType.getRawType();\n JsonAdapter annotation = getAnnotation(rawType);\n if (annotation == null) {\n- return null;\n+ return Optional.empty();\n }\n- return (TypeAdapter)\n- getTypeAdapter(constructorConstructor, gson, targetType, annotation, true);\n+ return Optional.ofNullable((TypeAdapter)\n+ getTypeAdapter(constructorConstructor, gson, targetType, annotation, true));\n }\n \n // Separate helper method to make sure callers create adapter in a consistent way\n@@ -121,7 +122,7 @@ public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapte\n factory = putFactoryAndGetCurrent(type.getRawType(), factory);\n }\n \n- typeAdapter = factory.create(gson, type);\n+ typeAdapter = factory.create(gson, type).orElse(null);\n } else if (instance instanceof JsonSerializer || instance instanceof JsonDeserializer) {\n JsonSerializer serializer =\n instance instanceof JsonSerializer ? (JsonSerializer) instance : null;\ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java\nindex 642586e3..82172b37 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java\n@@ -37,6 +37,7 @@ import java.util.ArrayList;\n import java.util.List;\n import java.util.Map;\n \n+import java.util.Optional;\n /**\n * Adapts maps to either JSON objects or JSON arrays.\n *\n@@ -123,12 +124,12 @@ public final class MapTypeAdapterFactory implements TypeAdapterFactory {\n }\n \n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n Type type = typeToken.getType();\n \n Class rawType = typeToken.getRawType();\n if (!Map.class.isAssignableFrom(rawType)) {\n- return null;\n+ return Optional.empty();\n }\n \n Type[] keyAndValueTypes = GsonTypes.getMapKeyAndValueTypes(type, rawType);\n@@ -148,7 +149,7 @@ public final class MapTypeAdapterFactory implements TypeAdapterFactory {\n @SuppressWarnings({\"unchecked\", \"rawtypes\"})\n // we don't define a type parameter for the key or value types\n TypeAdapter result = new Adapter(wrappedKeyAdapter, wrappedValueAdapter, constructor);\n- return result;\n+ return Optional.ofNullable(result);\n }\n \n /** Returns a type adapter that writes the value as a string. */\ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java\nindex 80eabccd..09353bb9 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java\n@@ -28,6 +28,7 @@ import com.google.gson.stream.JsonToken;\n import com.google.gson.stream.JsonWriter;\n import java.io.IOException;\n \n+import java.util.Optional;\n /** Type adapter for {@link Number}. */\n public final class NumberTypeAdapter extends TypeAdapter {\n /** Gson default factory using {@link ToNumberPolicy#LAZILY_PARSED_NUMBER}. */\n@@ -45,8 +46,8 @@ public final class NumberTypeAdapter extends TypeAdapter {\n return new TypeAdapterFactory() {\n @SuppressWarnings(\"unchecked\")\n @Override\n- public TypeAdapter create(Gson gson, TypeToken type) {\n- return type.getRawType() == Number.class ? (TypeAdapter) adapter : null;\n+ public Optional> create(Gson gson, TypeToken type) {\n+ return Optional.ofNullable(type.getRawType() == Number.class ? (TypeAdapter) adapter : null);\n }\n };\n }\ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java\nindex e08c41a4..81c30c64 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java\n@@ -33,6 +33,7 @@ import java.util.LinkedHashMap;\n import java.util.List;\n import java.util.Map;\n \n+import java.util.Optional;\n /**\n * Adapts types whose static type is only 'Object'. Uses getClass() on serialization and a\n * primitive/Map/List on deserialization.\n@@ -53,11 +54,11 @@ public final class ObjectTypeAdapter extends TypeAdapter {\n return new TypeAdapterFactory() {\n @SuppressWarnings(\"unchecked\")\n @Override\n- public TypeAdapter create(Gson gson, TypeToken type) {\n+ public Optional> create(Gson gson, TypeToken type) {\n if (type.getRawType() == Object.class) {\n- return (TypeAdapter) new ObjectTypeAdapter(gson, toNumberStrategy);\n+ return Optional.ofNullable((TypeAdapter) new ObjectTypeAdapter(gson, toNumberStrategy));\n }\n- return null;\n+ return Optional.empty();\n }\n };\n }\ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java\nindex f0c5a34c..d44a904f 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java\n@@ -56,6 +56,7 @@ import java.util.LinkedHashMap;\n import java.util.List;\n import java.util.Map;\n \n+import java.util.Optional;\n /** Type adapter that reflects over the fields and methods of a class. */\n public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {\n private final ConstructorConstructor constructorConstructor;\n@@ -107,11 +108,11 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {\n }\n \n @Override\n- public TypeAdapter create(Gson gson, TypeToken type) {\n+ public Optional> create(Gson gson, TypeToken type) {\n Class raw = type.getRawType();\n \n if (!Object.class.isAssignableFrom(raw)) {\n- return null; // it's a primitive!\n+ return Optional.empty(); // it's a primitive!\n }\n \n // Don't allow using reflection on anonymous and local classes because synthetic fields for\n@@ -120,7 +121,7 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {\n // This adapter just serializes and deserializes null, ignoring the actual values\n // This is done for backward compatibility; troubleshooting-wise it might be better to throw\n // exceptions\n- return new TypeAdapter() {\n+ return Optional.of(new TypeAdapter() {\n @Override\n public T read(JsonReader in) throws IOException {\n in.skipValue();\n@@ -136,7 +137,7 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {\n public String toString() {\n return \"AnonymousOrNonStaticLocalClassAdapter\";\n }\n- };\n+ });\n }\n \n FilterResult filterResult =\n@@ -157,12 +158,12 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {\n (TypeAdapter)\n new RecordAdapter<>(\n raw, getBoundFields(gson, type, raw, blockInaccessible, true), blockInaccessible);\n- return adapter;\n+ return Optional.ofNullable(adapter);\n }\n \n ObjectConstructor constructor = constructorConstructor.get(type, true);\n- return new FieldReflectionAdapter<>(\n- constructor, getBoundFields(gson, type, raw, blockInaccessible, false));\n+ return Optional.of(new FieldReflectionAdapter<>(\n+ constructor, getBoundFields(gson, type, raw, blockInaccessible, false)));\n }\n \n private static void checkAccessible(\ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java\nindex 62ea14d3..75ba3d10 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java\n@@ -33,6 +33,7 @@ import java.io.IOException;\n import java.lang.reflect.Type;\n import java.util.Objects;\n \n+import java.util.Optional;\n /**\n * Adapts a Gson 1.x tree-style adapter as a streaming TypeAdapter. Since the tree adapter may be\n * serialization-only or deserialization-only, this class has a facility to look up a delegate type\n@@ -176,15 +177,15 @@ public final class TreeTypeAdapter extends SerializationDelegatingTypeAdapter\n \n @SuppressWarnings(\"unchecked\") // guarded by typeToken.equals() call\n @Override\n- public TypeAdapter create(Gson gson, TypeToken type) {\n+ public Optional> create(Gson gson, TypeToken type) {\n boolean matches =\n exactType != null\n ? exactType.equals(type) || (matchRawType && exactType.getType() == type.getRawType())\n : hierarchyType.isAssignableFrom(type.getRawType());\n- return matches\n+ return Optional.ofNullable(matches\n ? new TreeTypeAdapter<>(\n (JsonSerializer) serializer, (JsonDeserializer) deserializer, gson, type, this)\n- : null;\n+ : null);\n }\n }\n \ndiff --git a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java\nindex 45f9536b..76d6da00 100644\n--- a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java\n+++ b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java\n@@ -56,6 +56,7 @@ import java.util.concurrent.atomic.AtomicLong;\n import java.util.concurrent.atomic.AtomicLongArray;\n import java.util.regex.Pattern;\n \n+import java.util.Optional;\n /**\n * Type adapters for basic types. More complex adapters exist as separate classes in the enclosing\n * package.\n@@ -995,8 +996,8 @@ public final class TypeAdapters {\n return new TypeAdapterFactory() {\n @SuppressWarnings(\"unchecked\") // we use a runtime check to make sure the 'T's equal\n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n- return typeToken.equals(type) ? (TypeAdapter) typeAdapter : null;\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n+ return Optional.ofNullable(typeToken.equals(type) ? (TypeAdapter) typeAdapter : null);\n }\n };\n }\n@@ -1006,8 +1007,8 @@ public final class TypeAdapters {\n return new TypeAdapterFactory() {\n @SuppressWarnings(\"unchecked\") // we use a runtime check to make sure the 'T's equal\n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n- return typeToken.getRawType() == type ? (TypeAdapter) typeAdapter : null;\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n+ return Optional.ofNullable(typeToken.getRawType() == type ? (TypeAdapter) typeAdapter : null);\n }\n \n @Override\n@@ -1023,9 +1024,9 @@ public final class TypeAdapters {\n return new TypeAdapterFactory() {\n @SuppressWarnings(\"unchecked\") // we use a runtime check to make sure the 'T's equal\n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n Class rawType = typeToken.getRawType();\n- return (rawType == unboxed || rawType == boxed) ? (TypeAdapter) typeAdapter : null;\n+ return Optional.ofNullable((rawType == unboxed || rawType == boxed) ? (TypeAdapter) typeAdapter : null);\n }\n \n @Override\n@@ -1047,9 +1048,9 @@ public final class TypeAdapters {\n return new TypeAdapterFactory() {\n @SuppressWarnings(\"unchecked\") // we use a runtime check to make sure the 'T's equal\n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n Class rawType = typeToken.getRawType();\n- return (rawType == base || rawType == sub) ? (TypeAdapter) typeAdapter : null;\n+ return Optional.ofNullable((rawType == base || rawType == sub) ? (TypeAdapter) typeAdapter : null);\n }\n \n @Override\n@@ -1074,12 +1075,12 @@ public final class TypeAdapters {\n return new TypeAdapterFactory() {\n @SuppressWarnings(\"unchecked\")\n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n Class requestedType = typeToken.getRawType();\n if (!clazz.isAssignableFrom(requestedType)) {\n- return null;\n+ return Optional.empty();\n }\n- return (TypeAdapter)\n+ return Optional.ofNullable((TypeAdapter)\n new TypeAdapter() {\n @Override\n public void write(JsonWriter out, T1 value) throws IOException {\n@@ -1100,7 +1101,7 @@ public final class TypeAdapters {\n }\n return result;\n }\n- };\n+ });\n }\n \n @Override\ndiff --git a/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java\nindex 1991daef..0a3d7d3c 100644\n--- a/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java\n+++ b/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java\n@@ -31,6 +31,7 @@ import java.text.SimpleDateFormat;\n import java.util.Date;\n import java.util.TimeZone;\n \n+import java.util.Optional;\n /**\n * Adapter for java.sql.Date. Although this class appears stateless, it is not. DateFormat captures\n * its time zone and locale when it is created, which gives this class state. DateFormat isn't\n@@ -42,10 +43,10 @@ final class SqlDateTypeAdapter extends TypeAdapter {\n new TypeAdapterFactory() {\n @SuppressWarnings(\"unchecked\") // we use a runtime check to make sure the 'T's equal\n @Override\n- public TypeAdapter create(Gson gson, TypeToken typeToken) {\n- return typeToken.getRawType() == java.sql.Date.class\n+ public Optional> create(Gson gson, TypeToken typeToken) {\n+ return Optional.ofNullable(typeToken.getRawType() == java.sql.Date.class\n ? (TypeAdapter) new SqlDateTypeAdapter()\n- : null;\n+ : null);\n }\n };\n \ndiff --git a/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java\nindex d63ae067..a9a28e11 100644\n--- a/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java\n+++ b/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java\n@@ -32,6 +32,7 @@ import java.text.SimpleDateFormat;\n import java.util.Date;\n import java.util.TimeZone;\n \n+import java.util.Optional;\n /**\n * Adapter for java.sql.Time. Although this class appears stateless, it is not. DateFormat captures\n * its time zone and locale when it is created, which gives this class state. DateFormat isn't\n@@ -43,10 +44,10 @@ final class SqlTimeTypeAdapter extends TypeAdapter