diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 76759228bb..532964f3a6 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -450,6 +450,23 @@ tasks: run_targets: - "//tools/rust_analyzer:gen_rust_project" - "//tools/rust_analyzer:discover_bazel_rust_project" + ide_integration_vscode_tests_linux: + name: IDE VSCode Tests + platform: ubuntu2204 + run_targets: + - "//tools/vscode:gen_launch_json" + - "//test/vscode:vscode_test" + ide_integration_vscode_tests_macos: + name: IDE VSCode Tests + platform: macos_arm64 + run_targets: + - "//tools/vscode:gen_launch_json" + - "//test/vscode:vscode_test" + ide_integration_vscode_tests_windows: + name: IDE VSCode Tests + platform: windows + run_targets: + - "//tools/vscode:gen_launch_json" crate_universe_examples_ubuntu2204: name: Crate Universe Examples platform: ubuntu2204 diff --git a/MODULE.bazel b/MODULE.bazel index d45eb78835..a0386a5016 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -69,6 +69,9 @@ use_repo( "rtra", "rtra__serde-1.0.219", "rtra__serde_json-1.0.143", + "rtvsc", + "rtvsc__serde-1.0.228", + "rtvsc__serde_json-1.0.145", "rules_rust_test_load_arbitrary_tool", "rules_rust_toolchain_test_target_json", ) diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index f84a9f4202..7a74424842 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -22,6 +22,7 @@ - [crate_universe (bzlmod)](crate_universe_bzlmod.md) - [crate_universe (WORKSPACE)](crate_universe_workspace.md) - [Upstream Tooling](./upstream_tooling.md) +- [IDE Integrations](./ide_integrations.md) - [Extensions](./extensions.md) - [bindgen](./rust_bindgen.md) - [mdbook](./rust_mdbook.md) diff --git a/docs/src/ide_integrations.md b/docs/src/ide_integrations.md new file mode 100644 index 0000000000..9907ff3dd6 --- /dev/null +++ b/docs/src/ide_integrations.md @@ -0,0 +1,31 @@ +# IDE Integrations + +## VSCode + +### Intellisense + +The best intellisense integrations to date are documented for [rust-analyzer](./rust_analyzer.md). Please refer to this documentation for setup instructions. + +### Debugging + +`rules_rust` offers tooling to generate VSCode targets for running `rust_binary` and `rust_test` targets with a debugger in VSCode. + +#### Prerequisites + +Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) extension in VSCode. + +#### Generate Launch Configurations + +Generate VSCode `launch.json` for debugging all Rust targets in the current workspace: + +```bash +bazel run @rules_rust//tools/vscode:gen_launch_json +``` + +To scope debug generated `launch.json` targets, query patterns can be passed: + +```bash +bazel run @rules_rust//tools/vscode:gen_launch_json -- //path/to/... +``` + +Bazel targets should now be available for debugging via the "Run and Debug" menu. diff --git a/test/deps.bzl b/test/deps.bzl index 210fe64518..a5c0364c25 100644 --- a/test/deps.bzl +++ b/test/deps.bzl @@ -6,6 +6,7 @@ load("//test/generated_inputs:external_repo.bzl", "generated_inputs_in_external_ load("//test/load_arbitrary_tool:load_arbitrary_tool_test.bzl", "load_arbitrary_tool_test") load("//test/rust_analyzer/3rdparty/crates:crates.bzl", rust_analyzer_test_crate_repositories = "crate_repositories") load("//test/unit/toolchain:toolchain_test_utils.bzl", "rules_rust_toolchain_test_target_json_repository") +load("//test/vscode/3rdparty/crates:crates.bzl", vscode_test_crate_repositories = "crate_repositories") _LIBC_BUILD_FILE_CONTENT = """\ load("@rules_rust//rust:defs.bzl", "rust_library") @@ -40,6 +41,7 @@ def rules_rust_test_deps(is_bzlmod = False): direct_deps = load_arbitrary_tool_test() direct_deps.extend(generated_inputs_in_external_repo()) direct_deps.extend(rust_analyzer_test_crate_repositories()) + direct_deps.extend(vscode_test_crate_repositories()) maybe( http_archive, diff --git a/test/rust_analyzer/rust_analyzer_test_runner.sh b/test/rust_analyzer/rust_analyzer_test_runner.sh index fb09a9665d..99f579b836 100755 --- a/test/rust_analyzer/rust_analyzer_test_runner.sh +++ b/test/rust_analyzer/rust_analyzer_test_runner.sh @@ -36,7 +36,7 @@ local_path_override( bazel_dep( name = "bazel_skylib", - version = "1.7.1", + version = "1.8.2", ) rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") @@ -102,13 +102,13 @@ function rust_analyzer_test() { else RUST_LOG="${rust_log}" bazel run "@rules_rust//tools/rust_analyzer:gen_rust_project" fi - + echo "Validating rust-project.json..." bazel run "@rules_rust//tools/rust_analyzer:validate" -- rust-project.json - + echo "Generating auto-discovery.json..." RUST_LOG="${rust_log}" bazel run "@rules_rust//tools/rust_analyzer:discover_bazel_rust_project" > auto-discovery.json - + echo "Building..." bazel build //... echo "Testing..." diff --git a/test/vscode/3rdparty/BUILD.bazel b/test/vscode/3rdparty/BUILD.bazel new file mode 100644 index 0000000000..f4fe45aa27 --- /dev/null +++ b/test/vscode/3rdparty/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_rust//crate_universe:defs.bzl", "crate", "crates_vendor") + +crates_vendor( + name = "crates_vendor", + mode = "remote", + packages = { + "serde": crate.spec( + features = ["derive"], + version = "1", + ), + "serde_json": crate.spec( + version = "1", + ), + }, + # Short for 'rust_test_vscode'. Keep this short to reduce + # the risk to bump into absolute path length issues on Windows. See: + # https://github.com/bazelbuild/rules_rust/issues/1120 + repository_name = "rtvsc", + tags = ["manual"], + vendor_path = "crates", +) diff --git a/test/vscode/3rdparty/crates/BUILD.bazel b/test/vscode/3rdparty/crates/BUILD.bazel new file mode 100644 index 0000000000..13aff40e5a --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.bazel @@ -0,0 +1,56 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +exports_files( + [ + "cargo-bazel.json", + "crates.bzl", + "defs.bzl", + ] + glob( + include = ["*.bazel"], + allow_empty = True, + ), +) + +filegroup( + name = "srcs", + srcs = glob( + include = [ + "*.bazel", + "*.bzl", + ], + allow_empty = True, + ), +) + +# Workspace Member Dependencies +alias( + name = "serde-1.0.228", + actual = "@rtvsc__serde-1.0.228//:serde", + tags = ["manual"], +) + +alias( + name = "serde", + actual = "@rtvsc__serde-1.0.228//:serde", + tags = ["manual"], +) + +alias( + name = "serde_json-1.0.145", + actual = "@rtvsc__serde_json-1.0.145//:serde_json", + tags = ["manual"], +) + +alias( + name = "serde_json", + actual = "@rtvsc__serde_json-1.0.145//:serde_json", + tags = ["manual"], +) diff --git a/test/vscode/3rdparty/crates/BUILD.itoa-1.0.15.bazel b/test/vscode/3rdparty/crates/BUILD.itoa-1.0.15.bazel new file mode 100644 index 0000000000..4bafcd507d --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.itoa-1.0.15.bazel @@ -0,0 +1,96 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "itoa", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2018", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=itoa", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.15", +) diff --git a/test/vscode/3rdparty/crates/BUILD.memchr-2.7.6.bazel b/test/vscode/3rdparty/crates/BUILD.memchr-2.7.6.bazel new file mode 100644 index 0000000000..0150b010fa --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.memchr-2.7.6.bazel @@ -0,0 +1,100 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "memchr", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "alloc", + "std", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=memchr", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "2.7.6", +) diff --git a/test/vscode/3rdparty/crates/BUILD.proc-macro2-1.0.101.bazel b/test/vscode/3rdparty/crates/BUILD.proc-macro2-1.0.101.bazel new file mode 100644 index 0000000000..664434516d --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.proc-macro2-1.0.101.bazel @@ -0,0 +1,168 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "proc_macro2", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "proc-macro", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=proc-macro2", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.101", + deps = [ + "@rtvsc__proc-macro2-1.0.101//:build_script_build", + "@rtvsc__unicode-ident-1.0.19//:unicode_ident", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "proc-macro", + ], + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2021", + pkg_name = "proc-macro2", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=proc-macro2", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.101", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/test/vscode/3rdparty/crates/BUILD.quote-1.0.41.bazel b/test/vscode/3rdparty/crates/BUILD.quote-1.0.41.bazel new file mode 100644 index 0000000000..794e176bcb --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.quote-1.0.41.bazel @@ -0,0 +1,168 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "quote", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "proc-macro", + ], + crate_root = "src/lib.rs", + edition = "2018", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=quote", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.41", + deps = [ + "@rtvsc__proc-macro2-1.0.101//:proc_macro2", + "@rtvsc__quote-1.0.41//:build_script_build", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "proc-macro", + ], + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2018", + pkg_name = "quote", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=quote", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.41", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/test/vscode/3rdparty/crates/BUILD.ryu-1.0.20.bazel b/test/vscode/3rdparty/crates/BUILD.ryu-1.0.20.bazel new file mode 100644 index 0000000000..b90bad7d5a --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.ryu-1.0.20.bazel @@ -0,0 +1,96 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "ryu", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2018", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=ryu", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.20", +) diff --git a/test/vscode/3rdparty/crates/BUILD.serde-1.0.228.bazel b/test/vscode/3rdparty/crates/BUILD.serde-1.0.228.bazel new file mode 100644 index 0000000000..bcd30dbf42 --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.serde-1.0.228.bazel @@ -0,0 +1,177 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "serde", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "derive", + "serde_derive", + "std", + ], + crate_root = "src/lib.rs", + edition = "2021", + proc_macro_deps = [ + "@rtvsc__serde_derive-1.0.228//:serde_derive", + ], + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.228", + deps = [ + "@rtvsc__serde-1.0.228//:build_script_build", + "@rtvsc__serde_core-1.0.228//:serde_core", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "derive", + "serde_derive", + "std", + ], + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2021", + pkg_name = "serde", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.228", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/test/vscode/3rdparty/crates/BUILD.serde_core-1.0.228.bazel b/test/vscode/3rdparty/crates/BUILD.serde_core-1.0.228.bazel new file mode 100644 index 0000000000..1f0153ab8e --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.serde_core-1.0.228.bazel @@ -0,0 +1,169 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "serde_core", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "result", + "std", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde_core", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.228", + deps = [ + "@rtvsc__serde_core-1.0.228//:build_script_build", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "result", + "std", + ], + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2021", + pkg_name = "serde_core", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde_core", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.228", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/test/vscode/3rdparty/crates/BUILD.serde_derive-1.0.228.bazel b/test/vscode/3rdparty/crates/BUILD.serde_derive-1.0.228.bazel new file mode 100644 index 0000000000..69ffdd3cb2 --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.serde_derive-1.0.228.bazel @@ -0,0 +1,104 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_proc_macro") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_proc_macro( + name = "serde_derive", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde_derive", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.228", + deps = [ + "@rtvsc__proc-macro2-1.0.101//:proc_macro2", + "@rtvsc__quote-1.0.41//:quote", + "@rtvsc__syn-2.0.107//:syn", + ], +) diff --git a/test/vscode/3rdparty/crates/BUILD.serde_json-1.0.145.bazel b/test/vscode/3rdparty/crates/BUILD.serde_json-1.0.145.bazel new file mode 100644 index 0000000000..9615b9a6a4 --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.serde_json-1.0.145.bazel @@ -0,0 +1,173 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load( + "@rules_rust//cargo:defs.bzl", + "cargo_build_script", + "cargo_toml_env_vars", +) +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "serde_json", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "std", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde_json", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.145", + deps = [ + "@rtvsc__itoa-1.0.15//:itoa", + "@rtvsc__memchr-2.7.6//:memchr", + "@rtvsc__ryu-1.0.20//:ryu", + "@rtvsc__serde_core-1.0.228//:serde_core", + "@rtvsc__serde_json-1.0.145//:build_script_build", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "default", + "std", + ], + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2021", + pkg_name = "serde_json", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=serde_json", + "manual", + "noclippy", + "norustfmt", + ], + version = "1.0.145", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/test/vscode/3rdparty/crates/BUILD.syn-2.0.107.bazel b/test/vscode/3rdparty/crates/BUILD.syn-2.0.107.bazel new file mode 100644 index 0000000000..a8213ba827 --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.syn-2.0.107.bazel @@ -0,0 +1,108 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "syn", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "clone-impls", + "derive", + "parsing", + "printing", + "proc-macro", + ], + crate_root = "src/lib.rs", + edition = "2021", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=syn", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "2.0.107", + deps = [ + "@rtvsc__proc-macro2-1.0.101//:proc_macro2", + "@rtvsc__quote-1.0.41//:quote", + "@rtvsc__unicode-ident-1.0.19//:unicode_ident", + ], +) diff --git a/test/vscode/3rdparty/crates/BUILD.unicode-ident-1.0.19.bazel b/test/vscode/3rdparty/crates/BUILD.unicode-ident-1.0.19.bazel new file mode 100644 index 0000000000..a7eb750bb6 --- /dev/null +++ b/test/vscode/3rdparty/crates/BUILD.unicode-ident-1.0.19.bazel @@ -0,0 +1,96 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_toml_env_vars") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +cargo_toml_env_vars( + name = "cargo_toml_env_vars", + src = "Cargo.toml", +) + +rust_library( + name = "unicode_ident", + srcs = glob( + include = ["**/*.rs"], + allow_empty = True, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2018", + rustc_env_files = [ + ":cargo_toml_env_vars", + ], + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=unicode-ident", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-apple-darwin": [], + "@rules_rust//rust/platform:aarch64-apple-ios": [], + "@rules_rust//rust/platform:aarch64-apple-ios-sim": [], + "@rules_rust//rust/platform:aarch64-linux-android": [], + "@rules_rust//rust/platform:aarch64-pc-windows-msvc": [], + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [], + "@rules_rust//rust/platform:aarch64-unknown-uefi": [], + "@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:armv7-linux-androideabi": [], + "@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [], + "@rules_rust//rust/platform:i686-apple-darwin": [], + "@rules_rust//rust/platform:i686-linux-android": [], + "@rules_rust//rust/platform:i686-pc-windows-msvc": [], + "@rules_rust//rust/platform:i686-unknown-freebsd": [], + "@rules_rust//rust/platform:i686-unknown-linux-gnu": [], + "@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [], + "@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu": [], + "@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [], + "@rules_rust//rust/platform:s390x-unknown-linux-gnu": [], + "@rules_rust//rust/platform:thumbv7em-none-eabi": [], + "@rules_rust//rust/platform:thumbv8m.main-none-eabi": [], + "@rules_rust//rust/platform:wasm32-unknown-emscripten": [], + "@rules_rust//rust/platform:wasm32-unknown-unknown": [], + "@rules_rust//rust/platform:wasm32-wasip1": [], + "@rules_rust//rust/platform:wasm32-wasip1-threads": [], + "@rules_rust//rust/platform:wasm32-wasip2": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-apple-ios": [], + "@rules_rust//rust/platform:x86_64-linux-android": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-freebsd": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [], + "@rules_rust//rust/platform:x86_64-unknown-none": [], + "@rules_rust//rust/platform:x86_64-unknown-uefi": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.19", +) diff --git a/test/vscode/3rdparty/crates/alias_rules.bzl b/test/vscode/3rdparty/crates/alias_rules.bzl new file mode 100644 index 0000000000..14b04c1272 --- /dev/null +++ b/test/vscode/3rdparty/crates/alias_rules.bzl @@ -0,0 +1,47 @@ +"""Alias that transitions its target to `compilation_mode=opt`. Use `transition_alias="opt"` to enable.""" + +load("@rules_cc//cc:defs.bzl", "CcInfo") +load("@rules_rust//rust:rust_common.bzl", "COMMON_PROVIDERS") + +def _transition_alias_impl(ctx): + # `ctx.attr.actual` is a list of 1 item due to the transition + providers = [ctx.attr.actual[0][provider] for provider in COMMON_PROVIDERS] + if CcInfo in ctx.attr.actual[0]: + providers.append(ctx.attr.actual[0][CcInfo]) + return providers + +def _change_compilation_mode(compilation_mode): + def _change_compilation_mode_impl(_settings, _attr): + return { + "//command_line_option:compilation_mode": compilation_mode, + } + + return transition( + implementation = _change_compilation_mode_impl, + inputs = [], + outputs = [ + "//command_line_option:compilation_mode", + ], + ) + +def _transition_alias_rule(compilation_mode): + return rule( + implementation = _transition_alias_impl, + provides = COMMON_PROVIDERS, + attrs = { + "actual": attr.label( + mandatory = True, + doc = "`rust_library()` target to transition to `compilation_mode=opt`.", + providers = COMMON_PROVIDERS, + cfg = _change_compilation_mode(compilation_mode), + ), + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), + }, + doc = "Transitions a Rust library crate to the `compilation_mode=opt`.", + ) + +transition_alias_dbg = _transition_alias_rule("dbg") +transition_alias_fastbuild = _transition_alias_rule("fastbuild") +transition_alias_opt = _transition_alias_rule("opt") diff --git a/test/vscode/3rdparty/crates/crates.bzl b/test/vscode/3rdparty/crates/crates.bzl new file mode 100644 index 0000000000..5762982f17 --- /dev/null +++ b/test/vscode/3rdparty/crates/crates.bzl @@ -0,0 +1,32 @@ +############################################################################### +# @generated +# This file is auto-generated by the cargo-bazel tool. +# +# DO NOT MODIFY: Local changes may be replaced in future executions. +############################################################################### +"""Rules for defining repositories for remote `crates_vendor` repositories""" + +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") + +# buildifier: disable=bzl-visibility +load("@rules_rust//crate_universe/private:crates_vendor.bzl", "crates_vendor_remote_repository") + +# buildifier: disable=bzl-visibility +load("//test/vscode/3rdparty/crates:defs.bzl", _crate_repositories = "crate_repositories") + +def crate_repositories(): + """Generates repositories for vendored crates. + + Returns: + A list of repos visible to the module through the module extension. + """ + maybe( + crates_vendor_remote_repository, + name = "rtvsc", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.bazel"), + defs_module = Label("//test/vscode/3rdparty/crates:defs.bzl"), + ) + + direct_deps = [struct(repo = "rtvsc", is_dev_dep = False)] + direct_deps.extend(_crate_repositories()) + return direct_deps diff --git a/test/vscode/3rdparty/crates/defs.bzl b/test/vscode/3rdparty/crates/defs.bzl new file mode 100644 index 0000000000..f76b533ceb --- /dev/null +++ b/test/vscode/3rdparty/crates/defs.bzl @@ -0,0 +1,526 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//test/vscode/3rdparty:crates_vendor +############################################################################### +""" +# `crates_repository` API + +- [aliases](#aliases) +- [crate_deps](#crate_deps) +- [all_crate_deps](#all_crate_deps) +- [crate_repositories](#crate_repositories) + +""" + +load("@bazel_skylib//lib:selects.bzl", "selects") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") + +############################################################################### +# MACROS API +############################################################################### + +# An identifier that represent common dependencies (unconditional). +_COMMON_CONDITION = "" + +def _flatten_dependency_maps(all_dependency_maps): + """Flatten a list of dependency maps into one dictionary. + + Dependency maps have the following structure: + + ```python + DEPENDENCIES_MAP = { + # The first key in the map is a Bazel package + # name of the workspace this file is defined in. + "workspace_member_package": { + + # Not all dependencies are supported for all platforms. + # the condition key is the condition required to be true + # on the host platform. + "condition": { + + # An alias to a crate target. # The label of the crate target the + # Aliases are only crate names. # package name refers to. + "package_name": "@full//:label", + } + } + } + ``` + + Args: + all_dependency_maps (list): A list of dicts as described above + + Returns: + dict: A dictionary as described above + """ + dependencies = {} + + for workspace_deps_map in all_dependency_maps: + for pkg_name, conditional_deps_map in workspace_deps_map.items(): + if pkg_name not in dependencies: + non_frozen_map = dict() + for key, values in conditional_deps_map.items(): + non_frozen_map.update({key: dict(values.items())}) + dependencies.setdefault(pkg_name, non_frozen_map) + continue + + for condition, deps_map in conditional_deps_map.items(): + # If the condition has not been recorded, do so and continue + if condition not in dependencies[pkg_name]: + dependencies[pkg_name].setdefault(condition, dict(deps_map.items())) + continue + + # Alert on any miss-matched dependencies + inconsistent_entries = [] + for crate_name, crate_label in deps_map.items(): + existing = dependencies[pkg_name][condition].get(crate_name) + if existing and existing != crate_label: + inconsistent_entries.append((crate_name, existing, crate_label)) + dependencies[pkg_name][condition].update({crate_name: crate_label}) + + return dependencies + +def crate_deps(deps, package_name = None): + """Finds the fully qualified label of the requested crates for the package where this macro is called. + + Args: + deps (list): The desired list of crate targets. + package_name (str, optional): The package name of the set of dependencies to look up. + Defaults to `native.package_name()`. + + Returns: + list: A list of labels to generated rust targets (str) + """ + + if not deps: + return [] + + if package_name == None: + package_name = native.package_name() + + # Join both sets of dependencies + dependencies = _flatten_dependency_maps([ + _NORMAL_DEPENDENCIES, + _NORMAL_DEV_DEPENDENCIES, + _PROC_MACRO_DEPENDENCIES, + _PROC_MACRO_DEV_DEPENDENCIES, + _BUILD_DEPENDENCIES, + _BUILD_PROC_MACRO_DEPENDENCIES, + ]).pop(package_name, {}) + + # Combine all conditional packages so we can easily index over a flat list + # TODO: Perhaps this should actually return select statements and maintain + # the conditionals of the dependencies + flat_deps = {} + for deps_set in dependencies.values(): + for crate_name, crate_label in deps_set.items(): + flat_deps.update({crate_name: crate_label}) + + missing_crates = [] + crate_targets = [] + for crate_target in deps: + if crate_target not in flat_deps: + missing_crates.append(crate_target) + else: + crate_targets.append(flat_deps[crate_target]) + + if missing_crates: + fail("Could not find crates `{}` among dependencies of `{}`. Available dependencies were `{}`".format( + missing_crates, + package_name, + dependencies, + )) + + return crate_targets + +def all_crate_deps( + normal = False, + normal_dev = False, + proc_macro = False, + proc_macro_dev = False, + build = False, + build_proc_macro = False, + package_name = None): + """Finds the fully qualified label of all requested direct crate dependencies \ + for the package where this macro is called. + + If no parameters are set, all normal dependencies are returned. Setting any one flag will + otherwise impact the contents of the returned list. + + Args: + normal (bool, optional): If True, normal dependencies are included in the + output list. + normal_dev (bool, optional): If True, normal dev dependencies will be + included in the output list.. + proc_macro (bool, optional): If True, proc_macro dependencies are included + in the output list. + proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are + included in the output list. + build (bool, optional): If True, build dependencies are included + in the output list. + build_proc_macro (bool, optional): If True, build proc_macro dependencies are + included in the output list. + package_name (str, optional): The package name of the set of dependencies to look up. + Defaults to `native.package_name()` when unset. + + Returns: + list: A list of labels to generated rust targets (str) + """ + + if package_name == None: + package_name = native.package_name() + + # Determine the relevant maps to use + all_dependency_maps = [] + if normal: + all_dependency_maps.append(_NORMAL_DEPENDENCIES) + if normal_dev: + all_dependency_maps.append(_NORMAL_DEV_DEPENDENCIES) + if proc_macro: + all_dependency_maps.append(_PROC_MACRO_DEPENDENCIES) + if proc_macro_dev: + all_dependency_maps.append(_PROC_MACRO_DEV_DEPENDENCIES) + if build: + all_dependency_maps.append(_BUILD_DEPENDENCIES) + if build_proc_macro: + all_dependency_maps.append(_BUILD_PROC_MACRO_DEPENDENCIES) + + # Default to always using normal dependencies + if not all_dependency_maps: + all_dependency_maps.append(_NORMAL_DEPENDENCIES) + + dependencies = _flatten_dependency_maps(all_dependency_maps).pop(package_name, None) + + if not dependencies: + if dependencies == None: + fail("Tried to get all_crate_deps for package " + package_name + " but that package had no Cargo.toml file") + else: + return [] + + crate_deps = list(dependencies.pop(_COMMON_CONDITION, {}).values()) + for condition, deps in dependencies.items(): + crate_deps += selects.with_or({ + tuple(_CONDITIONS[condition]): deps.values(), + "//conditions:default": [], + }) + + return crate_deps + +def aliases( + normal = False, + normal_dev = False, + proc_macro = False, + proc_macro_dev = False, + build = False, + build_proc_macro = False, + package_name = None): + """Produces a map of Crate alias names to their original label + + If no dependency kinds are specified, `normal` and `proc_macro` are used by default. + Setting any one flag will otherwise determine the contents of the returned dict. + + Args: + normal (bool, optional): If True, normal dependencies are included in the + output list. + normal_dev (bool, optional): If True, normal dev dependencies will be + included in the output list.. + proc_macro (bool, optional): If True, proc_macro dependencies are included + in the output list. + proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are + included in the output list. + build (bool, optional): If True, build dependencies are included + in the output list. + build_proc_macro (bool, optional): If True, build proc_macro dependencies are + included in the output list. + package_name (str, optional): The package name of the set of dependencies to look up. + Defaults to `native.package_name()` when unset. + + Returns: + dict: The aliases of all associated packages + """ + if package_name == None: + package_name = native.package_name() + + # Determine the relevant maps to use + all_aliases_maps = [] + if normal: + all_aliases_maps.append(_NORMAL_ALIASES) + if normal_dev: + all_aliases_maps.append(_NORMAL_DEV_ALIASES) + if proc_macro: + all_aliases_maps.append(_PROC_MACRO_ALIASES) + if proc_macro_dev: + all_aliases_maps.append(_PROC_MACRO_DEV_ALIASES) + if build: + all_aliases_maps.append(_BUILD_ALIASES) + if build_proc_macro: + all_aliases_maps.append(_BUILD_PROC_MACRO_ALIASES) + + # Default to always using normal aliases + if not all_aliases_maps: + all_aliases_maps.append(_NORMAL_ALIASES) + all_aliases_maps.append(_PROC_MACRO_ALIASES) + + aliases = _flatten_dependency_maps(all_aliases_maps).pop(package_name, None) + + if not aliases: + return dict() + + common_items = aliases.pop(_COMMON_CONDITION, {}).items() + + # If there are only common items in the dictionary, immediately return them + if not len(aliases.keys()) == 1: + return dict(common_items) + + # Build a single select statement where each conditional has accounted for the + # common set of aliases. + crate_aliases = {"//conditions:default": dict(common_items)} + for condition, deps in aliases.items(): + condition_triples = _CONDITIONS[condition] + for triple in condition_triples: + if triple in crate_aliases: + crate_aliases[triple].update(deps) + else: + crate_aliases.update({triple: dict(deps.items() + common_items)}) + + return select(crate_aliases) + +############################################################################### +# WORKSPACE MEMBER DEPS AND ALIASES +############################################################################### + +_NORMAL_DEPENDENCIES = { + "": { + _COMMON_CONDITION: { + "serde": Label("@rtvsc//:serde-1.0.228"), + "serde_json": Label("@rtvsc//:serde_json-1.0.145"), + }, + }, +} + +_NORMAL_ALIASES = { + "": { + _COMMON_CONDITION: { + }, + }, +} + +_NORMAL_DEV_DEPENDENCIES = { + "": { + }, +} + +_NORMAL_DEV_ALIASES = { + "": { + }, +} + +_PROC_MACRO_DEPENDENCIES = { + "": { + }, +} + +_PROC_MACRO_ALIASES = { + "": { + }, +} + +_PROC_MACRO_DEV_DEPENDENCIES = { + "": { + }, +} + +_PROC_MACRO_DEV_ALIASES = { + "": { + }, +} + +_BUILD_DEPENDENCIES = { + "": { + }, +} + +_BUILD_ALIASES = { + "": { + }, +} + +_BUILD_PROC_MACRO_DEPENDENCIES = { + "": { + }, +} + +_BUILD_PROC_MACRO_ALIASES = { + "": { + }, +} + +_CONDITIONS = { + "aarch64-apple-darwin": ["@rules_rust//rust/platform:aarch64-apple-darwin"], + "aarch64-apple-ios": ["@rules_rust//rust/platform:aarch64-apple-ios"], + "aarch64-apple-ios-sim": ["@rules_rust//rust/platform:aarch64-apple-ios-sim"], + "aarch64-linux-android": ["@rules_rust//rust/platform:aarch64-linux-android"], + "aarch64-pc-windows-msvc": ["@rules_rust//rust/platform:aarch64-pc-windows-msvc"], + "aarch64-unknown-fuchsia": ["@rules_rust//rust/platform:aarch64-unknown-fuchsia"], + "aarch64-unknown-linux-gnu": ["@rules_rust//rust/platform:aarch64-unknown-linux-gnu"], + "aarch64-unknown-nixos-gnu": ["@rules_rust//rust/platform:aarch64-unknown-nixos-gnu"], + "aarch64-unknown-nto-qnx710": ["@rules_rust//rust/platform:aarch64-unknown-nto-qnx710"], + "aarch64-unknown-uefi": ["@rules_rust//rust/platform:aarch64-unknown-uefi"], + "arm-unknown-linux-gnueabi": ["@rules_rust//rust/platform:arm-unknown-linux-gnueabi"], + "armv7-linux-androideabi": ["@rules_rust//rust/platform:armv7-linux-androideabi"], + "armv7-unknown-linux-gnueabi": ["@rules_rust//rust/platform:armv7-unknown-linux-gnueabi"], + "cfg(any())": [], + "i686-apple-darwin": ["@rules_rust//rust/platform:i686-apple-darwin"], + "i686-linux-android": ["@rules_rust//rust/platform:i686-linux-android"], + "i686-pc-windows-msvc": ["@rules_rust//rust/platform:i686-pc-windows-msvc"], + "i686-unknown-freebsd": ["@rules_rust//rust/platform:i686-unknown-freebsd"], + "i686-unknown-linux-gnu": ["@rules_rust//rust/platform:i686-unknown-linux-gnu"], + "powerpc-unknown-linux-gnu": ["@rules_rust//rust/platform:powerpc-unknown-linux-gnu"], + "riscv32imc-unknown-none-elf": ["@rules_rust//rust/platform:riscv32imc-unknown-none-elf"], + "riscv64gc-unknown-linux-gnu": ["@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu"], + "riscv64gc-unknown-none-elf": ["@rules_rust//rust/platform:riscv64gc-unknown-none-elf"], + "s390x-unknown-linux-gnu": ["@rules_rust//rust/platform:s390x-unknown-linux-gnu"], + "thumbv7em-none-eabi": ["@rules_rust//rust/platform:thumbv7em-none-eabi"], + "thumbv8m.main-none-eabi": ["@rules_rust//rust/platform:thumbv8m.main-none-eabi"], + "wasm32-unknown-emscripten": ["@rules_rust//rust/platform:wasm32-unknown-emscripten"], + "wasm32-unknown-unknown": ["@rules_rust//rust/platform:wasm32-unknown-unknown"], + "wasm32-wasip1": ["@rules_rust//rust/platform:wasm32-wasip1"], + "wasm32-wasip1-threads": ["@rules_rust//rust/platform:wasm32-wasip1-threads"], + "wasm32-wasip2": ["@rules_rust//rust/platform:wasm32-wasip2"], + "x86_64-apple-darwin": ["@rules_rust//rust/platform:x86_64-apple-darwin"], + "x86_64-apple-ios": ["@rules_rust//rust/platform:x86_64-apple-ios"], + "x86_64-linux-android": ["@rules_rust//rust/platform:x86_64-linux-android"], + "x86_64-pc-windows-msvc": ["@rules_rust//rust/platform:x86_64-pc-windows-msvc"], + "x86_64-unknown-freebsd": ["@rules_rust//rust/platform:x86_64-unknown-freebsd"], + "x86_64-unknown-fuchsia": ["@rules_rust//rust/platform:x86_64-unknown-fuchsia"], + "x86_64-unknown-linux-gnu": ["@rules_rust//rust/platform:x86_64-unknown-linux-gnu"], + "x86_64-unknown-nixos-gnu": ["@rules_rust//rust/platform:x86_64-unknown-nixos-gnu"], + "x86_64-unknown-none": ["@rules_rust//rust/platform:x86_64-unknown-none"], + "x86_64-unknown-uefi": ["@rules_rust//rust/platform:x86_64-unknown-uefi"], +} + +############################################################################### + +def crate_repositories(): + """A macro for defining repositories for all generated crates. + + Returns: + A list of repos visible to the module through the module extension. + """ + maybe( + http_archive, + name = "rtvsc__itoa-1.0.15", + sha256 = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c", + type = "tar.gz", + urls = ["https://static.crates.io/crates/itoa/1.0.15/download"], + strip_prefix = "itoa-1.0.15", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.itoa-1.0.15.bazel"), + ) + + maybe( + http_archive, + name = "rtvsc__memchr-2.7.6", + sha256 = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273", + type = "tar.gz", + urls = ["https://static.crates.io/crates/memchr/2.7.6/download"], + strip_prefix = "memchr-2.7.6", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.memchr-2.7.6.bazel"), + ) + + maybe( + http_archive, + name = "rtvsc__proc-macro2-1.0.101", + sha256 = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de", + type = "tar.gz", + urls = ["https://static.crates.io/crates/proc-macro2/1.0.101/download"], + strip_prefix = "proc-macro2-1.0.101", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.proc-macro2-1.0.101.bazel"), + ) + + maybe( + http_archive, + name = "rtvsc__quote-1.0.41", + sha256 = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1", + type = "tar.gz", + urls = ["https://static.crates.io/crates/quote/1.0.41/download"], + strip_prefix = "quote-1.0.41", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.quote-1.0.41.bazel"), + ) + + maybe( + http_archive, + name = "rtvsc__ryu-1.0.20", + sha256 = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f", + type = "tar.gz", + urls = ["https://static.crates.io/crates/ryu/1.0.20/download"], + strip_prefix = "ryu-1.0.20", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.ryu-1.0.20.bazel"), + ) + + maybe( + http_archive, + name = "rtvsc__serde-1.0.228", + sha256 = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e", + type = "tar.gz", + urls = ["https://static.crates.io/crates/serde/1.0.228/download"], + strip_prefix = "serde-1.0.228", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.serde-1.0.228.bazel"), + ) + + maybe( + http_archive, + name = "rtvsc__serde_core-1.0.228", + sha256 = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad", + type = "tar.gz", + urls = ["https://static.crates.io/crates/serde_core/1.0.228/download"], + strip_prefix = "serde_core-1.0.228", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.serde_core-1.0.228.bazel"), + ) + + maybe( + http_archive, + name = "rtvsc__serde_derive-1.0.228", + sha256 = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79", + type = "tar.gz", + urls = ["https://static.crates.io/crates/serde_derive/1.0.228/download"], + strip_prefix = "serde_derive-1.0.228", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.serde_derive-1.0.228.bazel"), + ) + + maybe( + http_archive, + name = "rtvsc__serde_json-1.0.145", + sha256 = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c", + type = "tar.gz", + urls = ["https://static.crates.io/crates/serde_json/1.0.145/download"], + strip_prefix = "serde_json-1.0.145", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.serde_json-1.0.145.bazel"), + ) + + maybe( + http_archive, + name = "rtvsc__syn-2.0.107", + sha256 = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b", + type = "tar.gz", + urls = ["https://static.crates.io/crates/syn/2.0.107/download"], + strip_prefix = "syn-2.0.107", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.syn-2.0.107.bazel"), + ) + + maybe( + http_archive, + name = "rtvsc__unicode-ident-1.0.19", + sha256 = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d", + type = "tar.gz", + urls = ["https://static.crates.io/crates/unicode-ident/1.0.19/download"], + strip_prefix = "unicode-ident-1.0.19", + build_file = Label("//test/vscode/3rdparty/crates:BUILD.unicode-ident-1.0.19.bazel"), + ) + + return [ + struct(repo = "rtvsc__serde-1.0.228", is_dev_dep = False), + struct(repo = "rtvsc__serde_json-1.0.145", is_dev_dep = False), + ] diff --git a/test/vscode/3rdparty/extensions.bzl b/test/vscode/3rdparty/extensions.bzl new file mode 100644 index 0000000000..0b6b79ad2b --- /dev/null +++ b/test/vscode/3rdparty/extensions.bzl @@ -0,0 +1,21 @@ +"""Bzlmod test extensions""" + +load("//test/vscode/3rdparty/crates:crates.bzl", "crate_repositories") + +def _vscode_test_impl(module_ctx): + deps = [] + + deps.extend(crate_repositories()) + + # is_dev_dep is ignored here. It's not relevant for internal_deps, as dev + # dependencies are only relevant for module extensions that can be used + # by other MODULES. + return module_ctx.extension_metadata( + root_module_direct_deps = [], + root_module_direct_dev_deps = [repo.repo for repo in deps], + ) + +vscode_test = module_extension( + doc = "An extension for vscode tests of rules_rust.", + implementation = _vscode_test_impl, +) diff --git a/test/vscode/BUILD.bazel b/test/vscode/BUILD.bazel new file mode 100644 index 0000000000..c43de025be --- /dev/null +++ b/test/vscode/BUILD.bazel @@ -0,0 +1,7 @@ +load("@rules_shell//shell:sh_binary.bzl", "sh_binary") + +sh_binary( + name = "vscode_test", + srcs = ["vscode_test_runner.sh"], + args = [package_name()], +) diff --git a/test/vscode/binaries_and_tests_test/BUILD.bazel b/test/vscode/binaries_and_tests_test/BUILD.bazel new file mode 100644 index 0000000000..667d5a9d0f --- /dev/null +++ b/test/vscode/binaries_and_tests_test/BUILD.bazel @@ -0,0 +1,26 @@ +load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library", "rust_test") + +rust_library( + name = "mylib", + srcs = ["lib.rs"], + edition = "2021", +) + +rust_binary( + name = "main_binary", + srcs = ["main.rs"], + edition = "2021", + deps = [":mylib"], +) + +rust_test( + name = "mylib_test", + crate = ":mylib", +) + +rust_test( + name = "test", + srcs = ["test.rs"], + edition = "2021", + deps = [":mylib"], +) diff --git a/test/vscode/binaries_and_tests_test/lib.rs b/test/vscode/binaries_and_tests_test/lib.rs new file mode 100644 index 0000000000..12ccdb024a --- /dev/null +++ b/test/vscode/binaries_and_tests_test/lib.rs @@ -0,0 +1,13 @@ +pub fn greet(name: &str) -> String { + format!("Hello, {}!", name) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_greet() { + assert_eq!(greet("World"), "Hello, World!"); + } +} diff --git a/test/vscode/binaries_and_tests_test/main.rs b/test/vscode/binaries_and_tests_test/main.rs new file mode 100644 index 0000000000..303a12fbef --- /dev/null +++ b/test/vscode/binaries_and_tests_test/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", mylib::greet("VSCode")); +} diff --git a/test/vscode/binaries_and_tests_test/test.rs b/test/vscode/binaries_and_tests_test/test.rs new file mode 100644 index 0000000000..559b07888b --- /dev/null +++ b/test/vscode/binaries_and_tests_test/test.rs @@ -0,0 +1,5 @@ +#[test] +fn test_integration() { + let result = mylib::greet("Integration"); + assert!(result.contains("Integration")); +} diff --git a/test/vscode/integration_tests/BUILD.bazel b/test/vscode/integration_tests/BUILD.bazel new file mode 100644 index 0000000000..a00b182763 --- /dev/null +++ b/test/vscode/integration_tests/BUILD.bazel @@ -0,0 +1,46 @@ +load("@rules_rust//rust:defs.bzl", "rust_test") + +rust_test( + name = "only_binaries_test", + srcs = ["only_binaries_test.rs"], + edition = "2021", + # LAUNCH_JSON env var will be set by the test runner script + # This target is tagged as manual since it's not expected to pass in + # contexts outside of `//test/vscode:vscode_test`. Run + # that target to execute this test. + tags = ["manual"], + deps = [ + "//test/vscode/3rdparty/crates:serde", + "//test/vscode/3rdparty/crates:serde_json", + ], +) + +rust_test( + name = "only_tests_test", + srcs = ["only_tests_test.rs"], + edition = "2021", + # LAUNCH_JSON env var will be set by the test runner script + # This target is tagged as manual since it's not expected to pass in + # contexts outside of `//test/vscode:vscode_test`. Run + # that target to execute this test. + tags = ["manual"], + deps = [ + "//test/vscode/3rdparty/crates:serde", + "//test/vscode/3rdparty/crates:serde_json", + ], +) + +rust_test( + name = "binaries_and_tests_test", + srcs = ["binaries_and_tests_test.rs"], + edition = "2021", + # LAUNCH_JSON env var will be set by the test runner script + # This target is tagged as manual since it's not expected to pass in + # contexts outside of `//test/vscode:vscode_test`. Run + # that target to execute this test. + tags = ["manual"], + deps = [ + "//test/vscode/3rdparty/crates:serde", + "//test/vscode/3rdparty/crates:serde_json", + ], +) diff --git a/test/vscode/integration_tests/binaries_and_tests_test.rs b/test/vscode/integration_tests/binaries_and_tests_test.rs new file mode 100644 index 0000000000..315f8e6a18 --- /dev/null +++ b/test/vscode/integration_tests/binaries_and_tests_test.rs @@ -0,0 +1,137 @@ +use std::env; +use std::fs; +use std::path::PathBuf; + +#[test] +fn test_binaries_and_tests() { + let launch_json_path = PathBuf::from(env::var("LAUNCH_JSON").unwrap()); + let content = fs::read_to_string(&launch_json_path) + .unwrap_or_else(|_| panic!("couldn't open {:?}", &launch_json_path)); + + let launch: serde_json::Value = serde_json::from_str(&content) + .unwrap_or_else(|e| panic!("Failed to parse launch.json: {}", e)); + + // Verify version + assert_eq!( + launch["version"].as_str(), + Some("0.2.0"), + "Should have version 0.2.0" + ); + + // Get configurations array + let configurations = launch["configurations"] + .as_array() + .expect("configurations should be an array"); + + // Should have exactly 3 configurations (1 binary + 2 tests) + assert_eq!( + configurations.len(), + 3, + "Should have 3 configurations (1 binary + 2 tests)" + ); + + // Collect configuration names + let names: Vec<&str> = configurations + .iter() + .filter_map(|c| c["name"].as_str()) + .collect(); + + // Check that we have configuration for the binary + assert!( + names.contains(&"Debug //binaries_and_tests_test:main_binary"), + "Should have configuration for //binaries_and_tests_test:main_binary" + ); + + // Check that we have configurations for both tests + assert!( + names.contains(&"Debug //binaries_and_tests_test:mylib_test"), + "Should have configuration for //binaries_and_tests_test:mylib_test" + ); + assert!( + names.contains(&"Debug //binaries_and_tests_test:test"), + "Should have configuration for //binaries_and_tests_test:test" + ); + + // All configurations should be lldb type with custom request + for config in configurations { + assert_eq!( + config["type"].as_str(), + Some("lldb"), + "All configurations should be lldb type" + ); + assert_eq!( + config["request"].as_str(), + Some("custom"), + "All configurations should have request=custom" + ); + + // Check sourceLanguages contains rust + let source_languages = config["sourceLanguages"] + .as_array() + .expect("sourceLanguages should be an array"); + let has_rust = source_languages + .iter() + .any(|lang| lang.as_str() == Some("rust")); + assert!(has_rust, "Should have rust in sourceLanguages"); + } + + // Count test configurations (should have BAZEL_TEST) vs binary configurations + let test_configs: Vec<&serde_json::Value> = configurations + .iter() + .filter(|c| { + c["env"] + .as_object() + .map(|env| env.contains_key("BAZEL_TEST")) + .unwrap_or(false) + }) + .collect(); + + let binary_configs: Vec<&serde_json::Value> = configurations + .iter() + .filter(|c| { + !c["env"] + .as_object() + .map(|env| env.contains_key("BAZEL_TEST")) + .unwrap_or(false) + }) + .collect(); + + assert_eq!(test_configs.len(), 2, "Should have 2 test configurations"); + assert_eq!( + binary_configs.len(), + 1, + "Should have 1 binary configuration" + ); + + // Verify test configurations have required env vars + for config in &test_configs { + let env = config["env"] + .as_object() + .expect("Test configuration should have env object"); + + assert_eq!( + env.get("BAZEL_TEST").and_then(|v| v.as_str()), + Some("1"), + "Test BAZEL_TEST should be set to '1'" + ); + assert!( + env.contains_key("TEST_TARGET"), + "Test configurations should have TEST_TARGET env var" + ); + } + + // Verify binary configuration does not have test env vars + for config in &binary_configs { + let env = &config["env"]; + if let Some(env_obj) = env.as_object() { + assert!( + !env_obj.contains_key("BAZEL_TEST"), + "Binary configuration should not have BAZEL_TEST" + ); + assert!( + !env_obj.contains_key("TEST_TARGET"), + "Binary configuration should not have TEST_TARGET" + ); + } + } +} diff --git a/test/vscode/integration_tests/only_binaries_test.rs b/test/vscode/integration_tests/only_binaries_test.rs new file mode 100644 index 0000000000..feabff4de0 --- /dev/null +++ b/test/vscode/integration_tests/only_binaries_test.rs @@ -0,0 +1,86 @@ +use std::env; +use std::fs; +use std::path::PathBuf; + +#[test] +fn test_only_binaries() { + let launch_json_path = PathBuf::from(env::var("LAUNCH_JSON").unwrap()); + let content = fs::read_to_string(&launch_json_path) + .unwrap_or_else(|_| panic!("couldn't open {:?}", &launch_json_path)); + + let launch: serde_json::Value = serde_json::from_str(&content) + .unwrap_or_else(|e| panic!("Failed to parse launch.json: {}", e)); + + // Verify version + assert_eq!( + launch["version"].as_str(), + Some("0.2.0"), + "Should have version 0.2.0" + ); + + // Get configurations array + let configurations = launch["configurations"] + .as_array() + .expect("configurations should be an array"); + + // Should have exactly 2 configurations + assert_eq!( + configurations.len(), + 2, + "Should have 2 configurations for 2 binaries" + ); + + // Collect configuration names + let names: Vec<&str> = configurations + .iter() + .filter_map(|c| c["name"].as_str()) + .collect(); + + // Check that we have configurations for both binaries + assert!( + names.contains(&"Debug //only_binaries_test:binary1"), + "Should have configuration for //only_binaries_test:binary1" + ); + assert!( + names.contains(&"Debug //only_binaries_test:binary2"), + "Should have configuration for //only_binaries_test:binary2" + ); + + // All configurations should be lldb type with custom request + for config in configurations { + assert_eq!( + config["type"].as_str(), + Some("lldb"), + "All configurations should be lldb type" + ); + assert_eq!( + config["request"].as_str(), + Some("custom"), + "All configurations should have request=custom" + ); + + // Check sourceLanguages contains rust + let source_languages = config["sourceLanguages"] + .as_array() + .expect("sourceLanguages should be an array"); + let has_rust = source_languages + .iter() + .any(|lang| lang.as_str() == Some("rust")); + assert!(has_rust, "Should have rust in sourceLanguages"); + } + + // Verify no test-related environment variables exist + for config in configurations { + let env = &config["env"]; + if let Some(env_obj) = env.as_object() { + assert!( + !env_obj.contains_key("BAZEL_TEST"), + "Binary configurations should not have BAZEL_TEST env var" + ); + assert!( + !env_obj.contains_key("TEST_TARGET"), + "Binary configurations should not have TEST_TARGET env var" + ); + } + } +} diff --git a/test/vscode/integration_tests/only_tests_test.rs b/test/vscode/integration_tests/only_tests_test.rs new file mode 100644 index 0000000000..4cfc6385f5 --- /dev/null +++ b/test/vscode/integration_tests/only_tests_test.rs @@ -0,0 +1,93 @@ +use std::env; +use std::fs; +use std::path::PathBuf; + +#[test] +fn test_only_tests() { + let launch_json_path = PathBuf::from(env::var("LAUNCH_JSON").unwrap()); + let content = fs::read_to_string(&launch_json_path) + .unwrap_or_else(|_| panic!("couldn't open {:?}", &launch_json_path)); + + let launch: serde_json::Value = serde_json::from_str(&content) + .unwrap_or_else(|e| panic!("Failed to parse launch.json: {}", e)); + + // Verify version + assert_eq!( + launch["version"].as_str(), + Some("0.2.0"), + "Should have version 0.2.0" + ); + + // Get configurations array + let configurations = launch["configurations"] + .as_array() + .expect("configurations should be an array"); + + // Should have exactly 2 configurations + assert_eq!( + configurations.len(), + 2, + "Should have 2 configurations for 2 tests" + ); + + // Collect configuration names + let names: Vec<&str> = configurations + .iter() + .filter_map(|c| c["name"].as_str()) + .collect(); + + // Check that we have configurations for both tests + assert!( + names.contains(&"Debug //only_tests_test:mylib_test"), + "Should have configuration for //only_tests_test:mylib_test" + ); + assert!( + names.contains(&"Debug //only_tests_test:test"), + "Should have configuration for //only_tests_test:test" + ); + + // All configurations should be lldb type with custom request + for config in configurations { + assert_eq!( + config["type"].as_str(), + Some("lldb"), + "All configurations should be lldb type" + ); + assert_eq!( + config["request"].as_str(), + Some("custom"), + "All configurations should have request=custom" + ); + + // Check sourceLanguages contains rust + let source_languages = config["sourceLanguages"] + .as_array() + .expect("sourceLanguages should be an array"); + let has_rust = source_languages + .iter() + .any(|lang| lang.as_str() == Some("rust")); + assert!(has_rust, "Should have rust in sourceLanguages"); + } + + // Verify test environment variables are present in all configurations + for config in configurations { + let env = config["env"] + .as_object() + .expect("Test configurations should have env object"); + + assert!( + env.contains_key("BAZEL_TEST"), + "Test configurations should have BAZEL_TEST env var. Config: {}", + config["name"] + ); + assert_eq!( + env.get("BAZEL_TEST").and_then(|v| v.as_str()), + Some("1"), + "BAZEL_TEST should be set to '1'" + ); + assert!( + env.contains_key("TEST_TARGET"), + "Test configurations should have TEST_TARGET env var" + ); + } +} diff --git a/test/vscode/no_targets_test/BUILD.bazel b/test/vscode/no_targets_test/BUILD.bazel new file mode 100644 index 0000000000..44cf2a27ac --- /dev/null +++ b/test/vscode/no_targets_test/BUILD.bazel @@ -0,0 +1,10 @@ +load("@rules_rust//rust:defs.bzl", "rust_library") + +# This BUILD file intentionally has no rust_binary or rust_test targets +# to test that gen_launch_json errors appropriately + +rust_library( + name = "mylib", + srcs = ["lib.rs"], + edition = "2021", +) diff --git a/test/vscode/no_targets_test/lib.rs b/test/vscode/no_targets_test/lib.rs new file mode 100644 index 0000000000..7c5393d6e6 --- /dev/null +++ b/test/vscode/no_targets_test/lib.rs @@ -0,0 +1,3 @@ +pub fn hello() -> &'static str { + "Hello, world!" +} diff --git a/test/vscode/only_binaries_test/BUILD.bazel b/test/vscode/only_binaries_test/BUILD.bazel new file mode 100644 index 0000000000..d782170c9a --- /dev/null +++ b/test/vscode/only_binaries_test/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_rust//rust:defs.bzl", "rust_binary") + +rust_binary( + name = "binary1", + srcs = ["binary1.rs"], + edition = "2021", +) + +rust_binary( + name = "binary2", + srcs = ["binary2.rs"], + edition = "2021", +) diff --git a/test/vscode/only_binaries_test/binary1.rs b/test/vscode/only_binaries_test/binary1.rs new file mode 100644 index 0000000000..bf46d93743 --- /dev/null +++ b/test/vscode/only_binaries_test/binary1.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Binary 1"); +} diff --git a/test/vscode/only_binaries_test/binary2.rs b/test/vscode/only_binaries_test/binary2.rs new file mode 100644 index 0000000000..50662b7bfc --- /dev/null +++ b/test/vscode/only_binaries_test/binary2.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Binary 2"); +} diff --git a/test/vscode/only_tests_test/BUILD.bazel b/test/vscode/only_tests_test/BUILD.bazel new file mode 100644 index 0000000000..920c66cb88 --- /dev/null +++ b/test/vscode/only_tests_test/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") + +rust_library( + name = "mylib", + srcs = ["lib.rs"], + edition = "2021", +) + +rust_test( + name = "mylib_test", + crate = ":mylib", +) + +rust_test( + name = "test", + srcs = ["test.rs"], + edition = "2021", + deps = [":mylib"], +) diff --git a/test/vscode/only_tests_test/lib.rs b/test/vscode/only_tests_test/lib.rs new file mode 100644 index 0000000000..17e05399cc --- /dev/null +++ b/test/vscode/only_tests_test/lib.rs @@ -0,0 +1,13 @@ +pub fn add(a: i32, b: i32) -> i32 { + a + b +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_add() { + assert_eq!(add(2, 2), 4); + } +} diff --git a/test/vscode/only_tests_test/test.rs b/test/vscode/only_tests_test/test.rs new file mode 100644 index 0000000000..23195a59d6 --- /dev/null +++ b/test/vscode/only_tests_test/test.rs @@ -0,0 +1,4 @@ +#[test] +fn test_add() { + assert_eq!(mylib::add(2, 2), 4); +} diff --git a/test/vscode/vscode_test_runner.sh b/test/vscode/vscode_test_runner.sh new file mode 100755 index 0000000000..36558fbad4 --- /dev/null +++ b/test/vscode/vscode_test_runner.sh @@ -0,0 +1,170 @@ +#!/usr/bin/env bash + +# This script creates a temporary workspace and generates `launch.json` +# files for each test subdirectory, then runs integration tests. + +set -euo pipefail + +if [[ -z "${BUILD_WORKSPACE_DIRECTORY:-}" ]]; then + >&2 echo "This script should be run under Bazel" + exit 1 +fi + +PACKAGE_NAME="$1" +if [[ -z "${PACKAGE_NAME:-}" ]]; then + >&2 echo "The first argument should be the package name of the test target" + exit 1 +fi + +function generate_workspace() { + local workspace_root="$1" + local package_dir="$2" + local temp_dir="$(mktemp -d -t rules_rust_test_vscode-XXXXXXXXXX)" + local new_workspace="${temp_dir}/rules_rust_test_vscode" + + mkdir -p "${new_workspace}" + cat <"${new_workspace}/MODULE.bazel" +module( + name = "rules_rust_test_vscode", + version = "0.0.0", +) +bazel_dep(name = "rules_rust", version = "0.0.0") +local_path_override( + module_name = "rules_rust", + path = "${BUILD_WORKSPACE_DIRECTORY}", +) + +bazel_dep( + name = "bazel_skylib", + version = "1.8.2", +) + +rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") +use_repo(rust, "rust_toolchains") +register_toolchains("@rust_toolchains//:all") + +vscode_test = use_extension("//test/vscode/3rdparty:extensions.bzl", "vscode_test", dev_dependency = True) +use_repo( + vscode_test, +EOF + + grep -hr "rtvsc" "${BUILD_WORKSPACE_DIRECTORY}/MODULE.bazel" >> "${new_workspace}/MODULE.bazel" + echo ")" >> "${new_workspace}/MODULE.bazel" + + cat <"${new_workspace}/.bazelrc" +build --keep_going +test --test_output=errors +EOF + + if [[ -f "${workspace_root}/.bazelversion" ]]; then + cp "${workspace_root}/.bazelversion" "${new_workspace}/.bazelversion" + fi + + # Copy test directories to the root of temp workspace + for test_dir in "${workspace_root}/${package_dir}"/*_test; do + if [[ -d "${test_dir}" ]]; then + local test_name="$(basename "${test_dir}")" + mkdir -p "${new_workspace}/${test_name}" + cp -r "${test_dir}"/* "${new_workspace}/${test_name}/" + fi + done + + # Copy integration_tests and 3rdparty to test/vscode/ + mkdir -p "${new_workspace}/${package_dir}" + cp -r "${workspace_root}/${package_dir}/integration_tests" "${new_workspace}/${package_dir}/" + cp -r "${workspace_root}/${package_dir}/3rdparty" "${new_workspace}/${package_dir}/" + + echo "${new_workspace}" +} + +function run_vscode_tests() { + local workspace="$1" + local rust_log="info" + if [[ -n "${VSCODE_TEST_DEBUG:-}" ]]; then + rust_log="debug" + fi + + pushd "${workspace}" &>/dev/null + + # Test 1: only_binaries_test + echo "Testing only_binaries_test..." + set +e + RUST_LOG="${rust_log}" bazel run @rules_rust//tools/vscode:gen_launch_json -- --output only_binaries_test/.vscode/launch.json //only_binaries_test/... + local exit_code=$? + set -e + if [[ ${exit_code} -ne 0 ]]; then + echo "ERROR: Failed to generate launch.json for only_binaries_test" + popd &>/dev/null + return 1 + fi + echo "Running integration test for only_binaries_test..." + LAUNCH_JSON="$(pwd)/only_binaries_test/.vscode/launch.json" bazel test //test/vscode/integration_tests:only_binaries_test --test_env=LAUNCH_JSON + + # Test 2: only_tests_test + echo "Testing only_tests_test..." + set +e + RUST_LOG="${rust_log}" bazel run @rules_rust//tools/vscode:gen_launch_json -- --output only_tests_test/.vscode/launch.json //only_tests_test/... + local exit_code=$? + set -e + if [[ ${exit_code} -ne 0 ]]; then + echo "ERROR: Failed to generate launch.json for only_tests_test" + popd &>/dev/null + return 1 + fi + echo "Running integration test for only_tests_test..." + LAUNCH_JSON="$(pwd)/only_tests_test/.vscode/launch.json" bazel test //test/vscode/integration_tests:only_tests_test --test_env=LAUNCH_JSON + + # Test 3: no_targets_test (should fail) + echo "Testing no_targets_test (expecting error)..." + set +e + RUST_LOG="${rust_log}" bazel run @rules_rust//tools/vscode:gen_launch_json -- //no_targets_test/... + local exit_code=$? + set -e + if [[ ${exit_code} -eq 0 ]]; then + echo "ERROR: Expected no_targets_test to fail but it succeeded" + popd &>/dev/null + return 1 + fi + echo "no_targets_test failed as expected" + + # Test 4: binaries_and_tests_test + echo "Testing binaries_and_tests_test..." + set +e + RUST_LOG="${rust_log}" bazel run @rules_rust//tools/vscode:gen_launch_json -- --output binaries_and_tests_test/.vscode/launch.json //binaries_and_tests_test/... + local exit_code=$? + set -e + if [[ ${exit_code} -ne 0 ]]; then + echo "ERROR: Failed to generate launch.json for binaries_and_tests_test" + popd &>/dev/null + return 1 + fi + echo "Running integration test for binaries_and_tests_test..." + LAUNCH_JSON="$(pwd)/binaries_and_tests_test/.vscode/launch.json" bazel test //test/vscode/integration_tests:binaries_and_tests_test --test_env=LAUNCH_JSON + + popd &>/dev/null + echo "All tests passed!" +} + +function cleanup() { + local workspace="$1" + pushd "${workspace}" &>/dev/null + bazel clean --expunge --async + popd &>/dev/null + if [[ -z "${VSCODE_TEST_DEBUG:-}" ]]; then + rm -rf "${workspace}" + else + echo "Debug workspace preserved at: ${workspace}" + fi +} + +function run_test_suite() { + local temp_workspace="$(generate_workspace "${BUILD_WORKSPACE_DIRECTORY}" "${PACKAGE_NAME}")" + echo "Generated workspace: ${temp_workspace}" + + run_vscode_tests "${temp_workspace}" + + echo "Done" + cleanup "${temp_workspace}" +} + +run_test_suite diff --git a/tools/vscode/BUILD.bazel b/tools/vscode/BUILD.bazel new file mode 100644 index 0000000000..98c74ce5c6 --- /dev/null +++ b/tools/vscode/BUILD.bazel @@ -0,0 +1,47 @@ +load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_test") + +alias( + name = "get_binary_path", + actual = select({ + "@platforms//os:windows": "get_binary_path.bat", + "//conditions:default": "get_binary_path.sh", + }), + visibility = ["//visibility:public"], +) + +rust_library( + name = "vscode", + srcs = [ + "src/lib.rs", + ], + edition = "2021", + deps = [ + "//tools/rust_analyzer/3rdparty/crates:anyhow", + "//tools/rust_analyzer/3rdparty/crates:camino", + "//tools/rust_analyzer/3rdparty/crates:log", + "//tools/rust_analyzer/3rdparty/crates:serde", + "//tools/rust_analyzer/3rdparty/crates:serde_json", + "//util/label", + ], +) + +rust_test( + name = "vscode_test", + crate = ":vscode", +) + +rust_binary( + name = "gen_launch_json", + srcs = ["src/bin/gen_launch_json.rs"], + edition = "2021", + visibility = ["//visibility:public"], + deps = [ + ":vscode", + "//tools/rust_analyzer/3rdparty/crates:anyhow", + "//tools/rust_analyzer/3rdparty/crates:camino", + "//tools/rust_analyzer/3rdparty/crates:clap", + "//tools/rust_analyzer/3rdparty/crates:env_logger", + "//tools/rust_analyzer/3rdparty/crates:log", + "//tools/rust_analyzer/3rdparty/crates:serde_json", + ], +) diff --git a/tools/vscode/get_binary_path.bat b/tools/vscode/get_binary_path.bat new file mode 100755 index 0000000000..93797f2db1 --- /dev/null +++ b/tools/vscode/get_binary_path.bat @@ -0,0 +1,35 @@ +@echo off +setlocal enabledelayedexpansion + +REM Check if an argument was provided +if "%~1"=="" ( + echo Usage: %~nx0 ^ >&2 + exit /b 1 +) + +REM Get the input path and convert to absolute path +set "input_path=%~f1" + +REM Check if the path contains "bazel-out" +echo !input_path! | findstr /C:"bazel-out" >nul +if errorlevel 1 ( + echo Error: Path does not contain 'bazel-out' >&2 + exit /b 1 +) + +REM Extract everything from "bazel-out" onwards +for /f "tokens=1,* delims==" %%a in ("!input_path:bazel-out=^=bazel-out!") do ( + set "result=%%b" +) + +REM Strip .runfiles wrapper path if present to get actual binary +REM bazel-out\...\bin\foo\bar.runfiles\_main\foo\bar -> bazel-out\...\bin\foo\bar +echo !result! | findstr /C:".runfiles\" >nul +if not errorlevel 1 ( + for /f "tokens=1 delims=." %%a in ("!result:.runfiles=^.runfiles!") do ( + set "result=%%a" + ) +) + +echo !result! 1>&2 +endlocal diff --git a/tools/vscode/get_binary_path.sh b/tools/vscode/get_binary_path.sh new file mode 100755 index 0000000000..3ebed05f5d --- /dev/null +++ b/tools/vscode/get_binary_path.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Check if an argument was provided +if [ $# -eq 0 ]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +# Get the input path +input_path="$1" + +# Convert to absolute path if relative +if [[ "$input_path" != /* ]]; then + # Extract directory and filename using parameter expansion + dir="${input_path%/*}" + file="${input_path##*/}" + + # Handle case where path has no directory component + if [[ "$dir" == "$input_path" ]]; then + dir="." + fi + + input_path="$(cd "$dir" && pwd)/$file" +fi + +# Check if the path contains "bazel-out" +if [[ "$input_path" == *"bazel-out"* ]]; then + # Extract everything from "bazel-out" onwards + result="${input_path#*bazel-out}" + full_path="bazel-out${result}" + + # Strip .runfiles wrapper path if present to get actual binary + # bazel-out/.../bin/foo/bar.runfiles/_main/foo/bar -> bazel-out/.../bin/foo/bar + if [[ "$full_path" == *".runfiles/"* ]]; then + full_path="${full_path%.runfiles/*}" + fi + + echo "$full_path" >&2 +else + echo "Error: Path does not contain 'bazel-out'" >&2 + exit 1 +fi diff --git a/tools/vscode/src/bin/gen_launch_json.rs b/tools/vscode/src/bin/gen_launch_json.rs new file mode 100644 index 0000000000..793b11b816 --- /dev/null +++ b/tools/vscode/src/bin/gen_launch_json.rs @@ -0,0 +1,159 @@ +use std::fs; +use std::path::Path; + +use anyhow::{Context, Result}; +use camino::Utf8PathBuf; +use clap::Parser; +use log::{debug, info}; +use serde_json::{json, Value}; +use vscode::{BazelInfo, LaunchConfigGenerator}; + +#[derive(Parser)] +#[command( + name = "generate_launch_json", + about = "Generate VSCode launch.json configurations for debugging Bazel Rust targets" +)] +struct Args { + /// Space separated list of target patterns that comes after all other args. + #[clap(default_value = "@//...")] + targets: Vec, + + /// Output file for launch configurations. If relative, the path will be joined with `workspace_root`. + #[arg(short, long, default_value = ".vscode/launch.json")] + output: Utf8PathBuf, + + /// Workspace root directory + #[arg(long, env = "BUILD_WORKSPACE_DIRECTORY")] + workspace_root: Option, + + /// Path to Bazel binary + #[arg(short, long, default_value = "bazel")] + bazel: Utf8PathBuf, + + /// Only generate configurations (don't write files) + #[arg(long)] + dry_run: bool, + + /// Don't pretty print generated JSON + #[arg(long)] + no_pretty: bool, + + /// Replace entire file instead of merging (removes all existing configurations) + #[arg(long)] + replace: bool, +} + +fn main() -> Result<()> { + env_logger::init(); + + let args = Args::parse(); + + let workspace_root = args + .workspace_root + .unwrap_or_else(|| Utf8PathBuf::from(".")); + + let bazel = args.bazel; + let bazel_info = BazelInfo::try_new(&bazel, &workspace_root)?; + + let generator = + LaunchConfigGenerator::new(workspace_root.clone(), bazel_info).with_bazel_binary(bazel); + + // Determine targets to process using query patterns + let query_patterns = if args.targets.is_empty() { + vec!["//...".to_string()] // Default to entire workspace + } else { + args.targets.clone() + }; + + info!( + "Querying Rust targets with patterns: {}", + query_patterns.join(", ") + ); + let target_infos = generator + .find_rust_targets(&query_patterns) + .context("Failed to find Rust targets")?; + info!( + "Found {} Rust targets ({} binaries, {} tests)", + target_infos.len(), + target_infos.iter().filter(|t| !t.is_test).count(), + target_infos.iter().filter(|t| t.is_test).count() + ); + + if target_infos.is_empty() { + anyhow::bail!("No valid Rust targets found"); + } + + let mut launch_configs = Vec::new(); + + for target_info in &target_infos { + let config = generator.generate_launch_config(target_info)?; + launch_configs.push(config); + debug!("Generated config for {}", target_info.label); + } + + // Make paths absolute relative to workspace root + let output_path = if args.output.is_absolute() { + args.output.clone() + } else { + workspace_root.join(&args.output) + }; + + // Create or merge launch.json + let launch_data = if args.replace { + // Replace mode: create completely new file + json!({ + "version": "0.2.0", + "configurations": launch_configs + }) + } else { + // Merge mode: merge with existing file (default) + generator.merge_launch_configs(&launch_configs, &output_path)? + }; + + if args.dry_run { + println!("=== launch.json ==="); + if args.no_pretty { + println!("{}", serde_json::to_string(&launch_data)?); + } else { + println!("{}", serde_json::to_string_pretty(&launch_data)?); + } + return Ok(()); + } + + // Write file + write_json_file(output_path.as_ref(), &launch_data, !args.no_pretty) + .context("Failed to write launch.json")?; + + if args.replace { + info!( + "Generated {} launch configurations in {}", + launch_configs.len(), + args.output + ); + } else { + info!( + "Merged {} launch configurations into {}", + launch_configs.len(), + args.output + ); + } + + Ok(()) +} + +fn write_json_file(path: &str, data: &Value, pretty: bool) -> Result<()> { + // Create parent directories if they don't exist + if let Some(parent) = Path::new(path).parent() { + fs::create_dir_all(parent).context("Failed to create output directory")?; + } + + let json_str = if pretty { + serde_json::to_string_pretty(data)? + } else { + serde_json::to_string(data)? + }; + + fs::write(path, json_str).context("Failed to write file")?; + + Ok(()) +} diff --git a/tools/vscode/src/lib.rs b/tools/vscode/src/lib.rs new file mode 100644 index 0000000000..7354cfc6aa --- /dev/null +++ b/tools/vscode/src/lib.rs @@ -0,0 +1,529 @@ +use std::collections::BTreeMap; +use std::fs; +use std::process::Command; + +use anyhow::{bail, Context, Result}; +use camino::{Utf8Path, Utf8PathBuf}; +use log::debug; +use serde::Serialize; +use serde_json::Value; + +pub struct BazelInfo { + pub output_base: String, + pub workspace: String, +} + +fn bazel_command(bazel: &Utf8Path, workspace_root: &Utf8Path) -> Command { + let mut cmd = Command::new(bazel); + cmd.current_dir(workspace_root); + cmd +} + +impl BazelInfo { + pub fn new(output_base: String, workspace: String) -> Self { + Self { + output_base, + workspace, + } + } + + pub fn try_new(bazel: &Utf8Path, workspace_root: &Utf8Path) -> anyhow::Result { + let output = bazel_command(bazel, workspace_root) + .arg("info") + .output() + .context("Failed to execute 'bazel info'")?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + bail!("bazel info failed: {}", stderr); + } + + let info_map: BTreeMap = String::from_utf8(output.stdout)? + .trim() + .lines() + .filter_map(|line| line.split_once(':')) + .map(|(k, v)| (k.to_owned(), v.trim().to_owned())) + .collect(); + + Ok(Self { + output_base: info_map + .get("output_base") + .context("Failed to query `bazel info output_base`")? + .clone(), + workspace: info_map + .get("workspace") + .context("Failed to query `bazel info workspace`")? + .clone(), + }) + } +} + +/// Information about a Bazel target for debugging. +#[derive(Debug, Clone)] +pub struct TargetInfo { + pub label: String, + pub binary_path: Utf8PathBuf, + pub is_test: bool, + pub target_kind: String, +} + +/// VSCode launch configuration for debugging. +#[derive(Debug, Serialize)] +pub struct LaunchConfig { + pub name: String, + pub r#type: String, + pub request: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub program: Option, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub args: Vec, + pub cwd: String, + #[serde(rename = "sourceLanguages")] + pub source_languages: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub env: Option>, + #[serde( + rename = "targetCreateCommands", + skip_serializing_if = "Option::is_none" + )] + pub target_create_commands: Option>, +} + +/// VSCode task configuration for building. +#[derive(Debug, Serialize)] +pub struct TaskConfig { + pub label: String, + pub r#type: String, + pub command: String, + pub args: Vec, + pub group: String, + pub presentation: TaskPresentation, + #[serde(rename = "problemMatcher")] + pub problem_matcher: Vec, +} + +#[derive(Debug, Serialize)] +pub struct TaskPresentation { + pub reveal: String, + pub panel: String, + #[serde(rename = "showReuseMessage")] + pub show_reuse_message: bool, + pub clear: bool, +} + +/// Generator for VSCode launch configurations. +pub struct LaunchConfigGenerator { + workspace_root: Utf8PathBuf, + bazel_binary: Utf8PathBuf, + bazel_info: BazelInfo, +} + +impl LaunchConfigGenerator { + pub fn new(workspace_root: Utf8PathBuf, bazel_info: BazelInfo) -> Self { + Self { + workspace_root, + bazel_binary: "bazel".into(), + bazel_info, + } + } + + pub fn with_bazel_binary(mut self, bazel: Utf8PathBuf) -> Self { + self.bazel_binary = bazel; + self + } + + /// Query information about multiple targets at once. + pub fn query_targets_batch(&mut self, targets: &[String]) -> Result> { + if targets.is_empty() { + return Ok(vec![]); + } + + // Get all target kinds in one query + let target_kinds = self.batch_query_target_kinds(targets)?; + + let mut results = Vec::new(); + for target in targets { + if let Some(target_kind) = target_kinds.get(target) { + let is_test = target_kind.contains("rust_test"); + + // We don't need to resolve binary paths now - that will happen at debug time + // Just create a placeholder path that will be resolved by the pre-launch task + results.push(TargetInfo { + label: target.to_string(), + binary_path: Utf8PathBuf::from(""), // Placeholder - resolved at debug time + is_test, + target_kind: target_kind.clone(), + }); + } + } + + Ok(results) + } + + /// Batch query target kinds for multiple targets at once. + fn batch_query_target_kinds(&self, targets: &[String]) -> Result> { + let target_pattern = targets.join(" + "); + + let output = bazel_command(&self.bazel_binary, &self.workspace_root) + .arg("query") + .arg("--output=label_kind") + .arg(&target_pattern) + .output() + .context("Failed to execute 'bazel query'")?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + bail!("bazel query failed for targets: {}", stderr); + } + + let stdout = String::from_utf8(output.stdout)?; + let mut result = BTreeMap::new(); + + for line in stdout.trim().lines() { + // Format: "rust_test rule //path/to:target" + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.len() >= 3 { + let kind = parts[0]; + let label = parts[2]; + + if !kind.starts_with("rust_") { + // Skip non-Rust targets + continue; + } + + result.insert(label.to_string(), kind.to_string()); + } + } + + Ok(result) + } + + /// Execute a Bazel query and return the results. + fn execute_query(&self, query_expr: &str) -> Result> { + debug!("Executing Bazel query: {}", query_expr); + + let output = bazel_command(&self.bazel_binary, &self.workspace_root) + .arg("query") + .arg(query_expr) + .output() + .context("Failed to execute 'bazel query'")?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + bail!("bazel query failed for '{}': {}", query_expr, stderr); + } + + let targets = String::from_utf8(output.stdout)? + .lines() + .map(|line| line.trim().to_string()) + .filter(|line| !line.is_empty()) + .collect::>(); + + debug!("Query returned {} targets", targets.len()); + Ok(targets) + } + + /// Find Rust targets using query patterns (similar to gen_rust_project approach). + /// Returns TargetInfo for all rust_binary and rust_test targets found. + pub fn find_rust_targets(&self, patterns: &[String]) -> Result> { + if patterns.is_empty() { + return Ok(vec![]); + } + + let target_pattern = patterns.join(" + "); + let mut results = Vec::new(); + + // Query rust_binary targets + let binary_query = format!("kind('rust_binary', {})", target_pattern); + let binary_targets = self.execute_query(&binary_query)?; + for label in binary_targets { + results.push(TargetInfo { + label, + binary_path: Utf8PathBuf::from(""), // Placeholder - resolved at debug time + is_test: false, + target_kind: "rust_binary".to_string(), + }); + } + + // Query rust_test targets + let test_query = format!("kind('rust_test', {})", target_pattern); + let test_targets = self.execute_query(&test_query)?; + for label in test_targets { + results.push(TargetInfo { + label, + binary_path: Utf8PathBuf::from(""), // Placeholder - resolved at debug time + is_test: true, + target_kind: "rust_test".to_string(), + }); + } + + Ok(results) + } + + /// Generate a launch configuration for a target. + pub fn generate_launch_config(&self, target_info: &TargetInfo) -> Result { + let name = format!("Debug {}", target_info.label); + + // Use CodeLLDB's "custom" request with Python scripting to build and get the binary path + // This consolidates everything into targetCreateCommands, no separate task needed + let target_create_commands = vec![ + // Multi-line Python script that: + // 1. Runs bazel with --run_under to get the binary path + // 2. Parses stderr for the bazel-out path + // 3. Creates the debug target + "script ".to_owned() + &[ + "import subprocess, os, sys".to_owned(), + format!("result = subprocess.run(['bazel', 'run', '--compilation_mode=dbg', '--strip=never', '--run_under=@rules_rust//tools/vscode_debug:get_binary_path', '{}'], stdout=subprocess.PIPE, text=True, cwd='${{workspaceFolder}}')", target_info.label), + "binary_path = result.stdout.strip().splitlines()[-1]".to_owned(), + format!("assert binary_path, 'No binary path output for {}'", target_info.label), + "abs_path = os.path.join('${workspaceFolder}', binary_path)".to_owned(), + "lldb.debugger.CreateTarget(abs_path)".to_owned(), + ].join("; ") + ]; + + let mut config = LaunchConfig { + name, + r#type: "lldb".to_string(), + request: "custom".to_string(), + program: None, + args: vec![], + cwd: self.workspace_root.to_string(), + source_languages: vec!["rust".to_string()], + env: None, + target_create_commands: Some(target_create_commands), + }; + + // Add test environment if this is a test target + if target_info.is_test { + let test_env = self.generate_test_environment(&target_info.label); + config.env = Some(test_env); + } + + Ok(config) + } + + /// Sanitize target name for use in filenames. + fn sanitize_target_name(&self, target: &str) -> String { + target.replace("//", "").replace([':', '/'], "_") + } + + /// Generate test environment variables based on Bazel test encyclopedia. + fn generate_test_environment(&self, target: &str) -> BTreeMap { + let workspace_name = &self.bazel_info.workspace; + + let mut env = BTreeMap::new(); + + let sanitized_name = self.sanitize_target_name(target); + let vscode_dir = self.workspace_root.join(".vscode"); + + // Core test environment variables from Bazel test encyclopedia + // https://bazel.build/reference/test-encyclopedia + env.insert("BAZEL_TEST".to_string(), "1".to_string()); + env.insert("TEST_TARGET".to_string(), target.to_string()); + env.insert("TEST_WORKSPACE".to_string(), workspace_name.clone()); + + // Test output directories (use .vscode subdirectories) + env.insert( + "TEST_TMPDIR".to_string(), + vscode_dir + .join(format!("bazel-test-tmp-{}", sanitized_name)) + .to_string(), + ); + env.insert( + "TEST_UNDECLARED_OUTPUTS_DIR".to_string(), + vscode_dir + .join(format!("bazel-test-outputs-{}", sanitized_name)) + .to_string(), + ); + env.insert( + "TEST_UNDECLARED_OUTPUTS_ANNOTATIONS_DIR".to_string(), + vscode_dir + .join(format!("bazel-test-annotations-{}", sanitized_name)) + .to_string(), + ); + + // Rust-specific + env.insert("RUST_BACKTRACE".to_string(), "all".to_string()); + + env + } + + /// Read existing launch.json file if it exists. + pub fn read_existing_launch_config(&self, path: &Utf8Path) -> Result> { + if !path.exists() { + return Ok(None); + } + + let content = fs::read_to_string(path) + .with_context(|| format!("Failed to read existing launch config from {}", path))?; + + let config: Value = serde_json::from_str(&content) + .with_context(|| format!("Failed to parse existing launch config from {}", path))?; + + Ok(Some(config)) + } + + /// Read existing tasks.json file if it exists. + pub fn read_existing_tasks_config(&self, path: &Utf8Path) -> Result> { + if !path.exists() { + return Ok(None); + } + + let content = fs::read_to_string(path) + .with_context(|| format!("Failed to read existing tasks config from {}", path))?; + + let config: Value = serde_json::from_str(&content) + .with_context(|| format!("Failed to parse existing tasks config from {}", path))?; + + Ok(Some(config)) + } + + /// Check if a configuration name matches our "Debug {label}" pattern and extract the label. + fn extract_debug_label(name: &str) -> Option<&str> { + name.strip_prefix("Debug ") + } + + /// Check if a task name matches our "bazel-debug: build {label}" pattern and extract the label. + fn extract_build_task_label(name: &str) -> Option<&str> { + name.strip_prefix("bazel-debug: build ") + } + + /// Filter out existing configurations that match our generated patterns. + fn filter_existing_configurations( + existing: &mut Value, + generated_targets: &[String], + ) -> Result<()> { + if let Some(configurations) = existing.get_mut("configurations") { + if let Some(configs_array) = configurations.as_array_mut() { + configs_array.retain(|config| { + if let Some(name) = config.get("name").and_then(|v| v.as_str()) { + if let Some(label) = Self::extract_debug_label(name) { + // Check if this is a valid Bazel label that we're generating + if label::analyze(label).is_ok() { + // If it's in our list of targets to generate, remove it + return !generated_targets.contains(&label.to_string()); + } + } + } + // Keep configurations that don't match our pattern + true + }); + } + } + Ok(()) + } + + /// Filter out existing tasks that match our generated patterns. + fn filter_existing_tasks(existing: &mut Value, generated_targets: &[String]) -> Result<()> { + if let Some(tasks) = existing.get_mut("tasks") { + if let Some(tasks_array) = tasks.as_array_mut() { + tasks_array.retain(|task| { + if let Some(label) = task.get("label").and_then(|v| v.as_str()) { + if let Some(target_label) = Self::extract_build_task_label(label) { + // Check if this is a valid Bazel label that we're generating + if label::analyze(target_label).is_ok() { + // If it's in our list of targets to generate, remove it + return !generated_targets.contains(&target_label.to_string()); + } + } + } + // Keep tasks that don't match our pattern + true + }); + } + } + Ok(()) + } + + /// Merge new configurations with existing launch.json. + pub fn merge_launch_configs( + &self, + new_configs: &[LaunchConfig], + existing_path: &Utf8Path, + ) -> Result { + let generated_targets: Vec = new_configs + .iter() + .filter_map(|config| Self::extract_debug_label(&config.name)) + .map(|s| s.to_string()) + .collect(); + + let mut result = + if let Some(mut existing) = self.read_existing_launch_config(existing_path)? { + // Remove existing configurations for targets we're regenerating + Self::filter_existing_configurations(&mut existing, &generated_targets)?; + existing + } else { + // Create new launch.json structure + serde_json::json!({ + "version": "0.2.0", + "configurations": [] + }) + }; + + // Add new configurations + if let Some(configurations) = result.get_mut("configurations") { + if let Some(configs_array) = configurations.as_array_mut() { + for config in new_configs { + configs_array.push(serde_json::to_value(config)?); + } + } + } + + Ok(result) + } + + /// Merge new tasks with existing tasks.json. + pub fn merge_tasks_configs( + &self, + new_tasks: &[TaskConfig], + existing_path: &Utf8Path, + ) -> Result { + let generated_targets: Vec = new_tasks + .iter() + .filter_map(|task| Self::extract_build_task_label(&task.label)) + .map(|s| s.to_string()) + .collect(); + + let mut result = + if let Some(mut existing) = self.read_existing_tasks_config(existing_path)? { + // Remove existing tasks for targets we're regenerating + Self::filter_existing_tasks(&mut existing, &generated_targets)?; + existing + } else { + // Create new tasks.json structure + serde_json::json!({ + "version": "2.0.0", + "tasks": [] + }) + }; + + // Add new tasks + if let Some(tasks) = result.get_mut("tasks") { + if let Some(tasks_array) = tasks.as_array_mut() { + for task in new_tasks { + tasks_array.push(serde_json::to_value(task)?); + } + } + } + + Ok(result) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_target_info_creation() { + let target_info = TargetInfo { + label: "//test:my_test".to_string(), + binary_path: "/path/to/binary".into(), + is_test: true, + target_kind: "rust_test rule".to_string(), + }; + + assert_eq!(target_info.label, "//test:my_test"); + assert!(target_info.is_test); + } +}