diff --git a/crates/ide-sdk/src/go.rs b/crates/ide-sdk/src/go.rs index e29fce2a3..34bc3d9a7 100644 --- a/crates/ide-sdk/src/go.rs +++ b/crates/ide-sdk/src/go.rs @@ -77,7 +77,11 @@ pub fn apply_to_run(config: &mut ide_run::RunConfig, tags: &GoBuildTags) { } } } - if config.extras.params.get("useTags").is_some_and(|v| v == "true") { + if config.extras.params.get("useTags").is_none_or(|value| value != "false") + && config.args.first().is_some_and(|operation| { + matches!(operation.as_str(), "run" | "build" | "test" | "generate" | "vet" | "list" | "install" | "clean") + }) + { let extra = settings["buildFlags"] .as_array() .into_iter() @@ -205,6 +209,27 @@ mod command_tests { use super::*; use std::collections::BTreeMap; + #[test] + fn detected_go_runs_inherit_tags_only_for_commands_that_accept_build_flags() { + let tags = GoBuildTags { custom: "integration".into(), ..Default::default() }; + for operation in + ["run", "build", "test", "generate", "vet", "list", "install", "clean", "mod", "work", "env", "version"] + { + let mut config: ide_run::RunConfig = serde_json::from_value(json!({ + "id":"go", "name":"Go", "kind":"go", "command":"go", "args":[operation, "."], + "env":{}, "detected":true, "isTest":false + })) + .unwrap(); + let accepts = !["mod", "work", "env", "version"].contains(&operation); + apply_to_run(&mut config, &tags); + assert_eq!(config.args.iter().any(|flag| flag == "-tags=integration"), accepts, "{operation}"); + config.args = vec![operation.into(), "-tags=explicit".into(), ".".into()]; + config.extras.params.insert("useTags".into(), "false".into()); + apply_to_run(&mut config, &tags); + assert_eq!(config.args, [operation, "-tags=explicit", "."]); + } + } + #[test] fn file_tests_debug_the_real_package_and_keep_sibling_test_helpers() { if crate::exec::which("go").is_none() { diff --git a/src/features/debugger/__tests__/launch.test.ts b/src/features/debugger/__tests__/launch.test.ts index 4c60822c3..4658aa663 100644 --- a/src/features/debugger/__tests__/launch.test.ts +++ b/src/features/debugger/__tests__/launch.test.ts @@ -236,7 +236,7 @@ describe("run config → launch config", () => { it("delve: debug mode for run, test mode for test", () => { const run = launchConfigFor(rc({ kind: "go", command: "go", args: ["run", "."], debugAdapter: "delve" }), "/p")!; expect(run.program).toBe("/p"); - expect(extra(run)).toEqual({ mode: "debug" }); + expect(extra(run)).toEqual({ mode: "debug", __goToolArgs: [], __goUseTags: true }); const sub = launchConfigFor( rc({ kind: "go", command: "go", args: ["run", "./cmd/api"], debugAdapter: "delve" }), "/p", @@ -246,7 +246,7 @@ describe("run config → launch config", () => { rc({ kind: "go", command: "go", args: ["test", "./..."], debugAdapter: "delve" }), "/p", )!; - expect(extra(test)).toEqual({ mode: "test" }); + expect(extra(test)).toEqual({ mode: "test", __goToolArgs: [], __goUseTags: true }); expect(test.program).toBe("/p"); // A gutter test / subtest: the package, and `-run` for the test binary. const one = launchConfigFor( @@ -398,3 +398,19 @@ it("netcoredbg launches the evaluated DLL with resolved profile arguments, env a expect(launchConfigFor({ ...c, params: { ...c.params, programArgs: "" } }, "/repo")?.args).toEqual(["--profile"]); expect(launchConfigFor({ ...c, params: {} }, "/repo")).toBeNull(); }); + +it("raw and typed Go debug configurations inherit custom tags unless explicitly disabled", () => { + for (const typed of [false, true]) { + for (const useTags of [undefined, "true", "false"]) { + const params = { + ...(typed ? { goKind: "test", scope: "package", target: "." } : {}), + ...(useTags === undefined ? {} : { useTags }), + }; + const launch = launchConfigFor( + rc({ kind: "go", command: "go", args: ["test", "-tags=explicit", "."], debugAdapter: "delve", params }), + "/p", + )!; + expect(extra(launch).__goUseTags).toBe(useTags !== "false"); + } + } +}); diff --git a/src/features/debugger/launch.ts b/src/features/debugger/launch.ts index e5fb36dae..ac8a2c00d 100644 --- a/src/features/debugger/launch.ts +++ b/src/features/debugger/launch.ts @@ -219,7 +219,7 @@ function delveLaunch(rc: RunConfig, cwd: string, root: string): LaunchConfig { dlvCwd: module, ...(p.scope === "file" ? { __goFiles: target.split("|").map((f) => join(module, f.trim())) } : {}), __goToolArgs: toolArgs, - __goUseTags: p.useTags === "true", + __goUseTags: p.useTags !== "false", ...(p.outputDir ? { output: join(root, `${p.outputDir}/go-debug`) } : {}), }); return out; @@ -276,6 +276,8 @@ function delveLaunch(rc: RunConfig, cwd: string, root: string): LaunchConfig { out.extraJson = JSON.stringify({ mode: test ? "test" : "debug", ...(flags.length ? { buildFlags: formatArgs(flags) } : {}), + __goToolArgs: flags, + __goUseTags: rc.params?.useTags !== "false", }); return out; } diff --git a/src/features/run/testing/rerun.test.ts b/src/features/run/testing/rerun.test.ts index b22ed4ad2..c69229199 100644 --- a/src/features/run/testing/rerun.test.ts +++ b/src/features/run/testing/rerun.test.ts @@ -326,3 +326,11 @@ describe("exact Go test and benchmark selections", () => { expect(config!.args).toEqual(["test", "-race", "-bench", ".", "example.com/p"]); }); }); + +it("keeps inherited Go build tags enabled when deriving a typed package rerun", () => { + const config = { + ...cfg("go", "go", ["test", "./..."]), + params: { goKind: "test", scope: "package", target: "./..." }, + }; + expect(rerunFailedConfig(config, [["example.com/p", "TestChosen"]])!.params?.useTags).toBe("true"); +}); diff --git a/src/features/run/testing/rerun.ts b/src/features/run/testing/rerun.ts index e2a9bec5b..6bc8d6dc6 100644 --- a/src/features/run/testing/rerun.ts +++ b/src/features/run/testing/rerun.ts @@ -225,7 +225,7 @@ export function testsConfig(config: RunConfig, paths: string[][], name: string): toolArgs: formatArgs(dropFlag(goTestParts(args).flags, ["-run", "-test.run"])), programArgs: formatArgs(goTestParts(args).program.slice(1)), } - : { module: config.params.module ?? "", useTags: config.params.useTags ?? "false" }, + : { module: config.params.module ?? "", useTags: config.params.useTags ?? "true" }, } : {}), };