Skip to content

Commit 685dfda

Browse files
authored
Fixed use of rust-analyzer with rust_static_library and rust_shared_library (#1482)
1 parent 2d7f945 commit 685dfda

File tree

8 files changed

+177
-15
lines changed

8 files changed

+177
-15
lines changed

examples/WORKSPACE.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ rust_register_toolchains(
1616
edition = "2018",
1717
)
1818

19+
load("@rules_rust//tools/rust_analyzer:deps.bzl", "rust_analyzer_dependencies")
20+
21+
rust_analyzer_dependencies()
22+
1923
load("@rules_rust//bindgen:repositories.bzl", "rust_bindgen_dependencies", "rust_bindgen_register_toolchains")
2024

2125
rust_bindgen_dependencies()

rust/private/rust_analyzer.bzl

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ RustAnalyzerInfo = provider(
3939
)
4040

4141
def _rust_analyzer_aspect_impl(target, ctx):
42-
if rust_common.crate_info not in target:
42+
if rust_common.crate_info not in target and rust_common.test_crate_info not in target:
4343
return []
4444

4545
toolchain = find_toolchain(ctx)
@@ -70,7 +70,12 @@ def _rust_analyzer_aspect_impl(target, ctx):
7070

7171
crate_spec = ctx.actions.declare_file(ctx.label.name + ".rust_analyzer_crate_spec")
7272

73-
crate_info = target[rust_common.crate_info]
73+
if rust_common.crate_info in target:
74+
crate_info = target[rust_common.crate_info]
75+
elif rust_common.test_crate_info in target:
76+
crate_info = target[rust_common.test_crate_info].crate
77+
else:
78+
fail("Unexpected target type: {}".format(target))
7479

7580
rust_analyzer_info = RustAnalyzerInfo(
7681
crate = crate_info,
@@ -101,7 +106,14 @@ def find_proc_macro_dylib_path(toolchain, target):
101106
Returns:
102107
(path): The path to the proc macro dylib, or None if this crate is not a proc-macro.
103108
"""
104-
if target[rust_common.crate_info].type != "proc-macro":
109+
if rust_common.crate_info in target:
110+
crate_info = target[rust_common.crate_info]
111+
elif rust_common.test_crate_info in target:
112+
crate_info = target[rust_common.test_crate_info].crate
113+
else:
114+
return None
115+
116+
if crate_info.type != "proc-macro":
105117
return None
106118

107119
dylib_ext = system_to_dylib_ext(triple_to_system(toolchain.target_triple))

test/rust_analyzer/rust_analyzer_test_runner.sh

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function generate_workspace() {
2121
local new_workspace="${temp_dir}/rules_rust_test_rust_analyzer"
2222

2323
mkdir -p "${new_workspace}"
24-
cat << EOF > "${new_workspace}/WORKSPACE.bazel"
24+
cat <<EOF >"${new_workspace}/WORKSPACE.bazel"
2525
workspace(name = "rules_rust_test_rust_analyzer")
2626
local_repository(
2727
name = "rules_rust",
@@ -33,7 +33,7 @@ load("@rules_rust//tools/rust_analyzer:deps.bzl", "rust_analyzer_dependencies")
3333
rust_analyzer_dependencies()
3434
EOF
3535

36-
cat << EOF > "${new_workspace}/.bazelrc"
36+
cat <<EOF >"${new_workspace}/.bazelrc"
3737
build --keep_going
3838
test --test_output=errors
3939
# The 'strict' config is used to ensure extra checks are run on the test
@@ -45,35 +45,48 @@ build:strict --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect
4545
build:strict --output_groups=+clippy_checks
4646
EOF
4747

48-
echo "${new_workspace}"
48+
echo "${new_workspace}"
4949
}
5050

5151
function rust_analyzer_test() {
5252
local source_dir="$1"
5353
local workspace="$2"
54-
54+
local generator_arg="$3"
55+
5556
echo "Testing '$(basename "${source_dir}")'"
56-
rm -f "${workspace}"/*.rs "${workspace}"/*.json "${workspace}/BUILD.bazel"
57+
rm -f "${workspace}"/*.rs "${workspace}"/*.json "${workspace}"/*.bzl "${workspace}/BUILD.bazel" "${workspace}/BUILD.bazel-e"
5758
cp -r "${source_dir}"/* "${workspace}"
58-
59+
5960
# Drop the 'manual' tags
6061
if [ "$(uname)" == "Darwin" ]; then
6162
SEDOPTS=(-i '' -e)
6263
else
6364
SEDOPTS=(-i)
6465
fi
6566
sed ${SEDOPTS[@]} 's/"manual"//' "${workspace}/BUILD.bazel"
66-
67-
pushd "${workspace}" &> /dev/null
67+
68+
pushd "${workspace}" &>/dev/null
6869
echo "Generating rust-project.json..."
69-
bazel run "@rules_rust//tools/rust_analyzer:gen_rust_project" -- //:mylib_test
70+
if [[ -n "${generator_arg}" ]]; then
71+
bazel run "@rules_rust//tools/rust_analyzer:gen_rust_project" -- "${generator_arg}"
72+
else
73+
bazel run "@rules_rust//tools/rust_analyzer:gen_rust_project"
74+
fi
7075
echo "Building..."
7176
bazel build //...
7277
echo "Testing..."
7378
bazel test //...
7479
echo "Building with Aspects..."
7580
bazel build //... --config=strict
76-
popd &> /dev/null
81+
popd &>/dev/null
82+
}
83+
84+
function cleanup() {
85+
local workspace="$1"
86+
pushd "${workspace}" &>/dev/null
87+
bazel clean --async
88+
popd &>/dev/null
89+
rm -rf "${workspace}"
7790
}
7891

7992
function run_test_suite() {
@@ -86,10 +99,20 @@ function run_test_suite() {
8699
continue
87100
fi
88101

89-
rust_analyzer_test "${test_dir}" "${temp_workspace}"
102+
# Some tests have arguments that need to be passed to the rust-project.json generator.
103+
if [[ "${test_dir}" = "aspect_traversal_test" ]]; then
104+
test_arg="//mylib_test"
105+
elif [[ "${test_dir}" = "merging_crates_test" ]]; then
106+
test_arg="//mylib_test"
107+
else
108+
test_arg=""
109+
fi
110+
111+
rust_analyzer_test "${test_dir}" "${temp_workspace}" "${test_arg}"
90112
done
91113

92-
rm -rf "${temp_workspace}"
114+
echo "Done"
115+
cleanup "${temp_workspace}"
93116
}
94117

95118
run_test_suite
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
load(
2+
"@rules_rust//rust:defs.bzl",
3+
"rust_shared_library",
4+
"rust_static_library",
5+
"rust_test",
6+
)
7+
8+
rust_shared_library(
9+
name = "greeter_cdylib",
10+
srcs = [
11+
"greeter.rs",
12+
"shared_lib.rs",
13+
],
14+
crate_root = "shared_lib.rs",
15+
edition = "2018",
16+
)
17+
18+
rust_static_library(
19+
name = "greeter_staticlib",
20+
srcs = [
21+
"greeter.rs",
22+
"static_lib.rs",
23+
],
24+
crate_root = "static_lib.rs",
25+
edition = "2018",
26+
)
27+
28+
rust_test(
29+
name = "rust_project_json_test",
30+
srcs = ["rust_project_json_test.rs"],
31+
data = [":rust-project.json"],
32+
edition = "2018",
33+
env = {"RUST_PROJECT_JSON": "$(rootpath :rust-project.json)"},
34+
# This target is tagged as manual since it's not expected to pass in
35+
# contexts outside of `//test/rust_analyzer:rust_analyzer_test`. Run
36+
# that target to execute this test.
37+
tags = ["manual"],
38+
)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/// Object that displays a greeting.
2+
pub struct Greeter {
3+
greeting: String,
4+
}
5+
6+
/// Implementation of Greeter.
7+
impl Greeter {
8+
/// Constructs a new `Greeter`.
9+
///
10+
/// # Examples
11+
///
12+
/// ```
13+
/// use hello_lib::greeter::Greeter;
14+
///
15+
/// let greeter = Greeter::new("Hello");
16+
/// ```
17+
pub fn new(greeting: &str) -> Greeter {
18+
Greeter {
19+
greeting: greeting.to_string(),
20+
}
21+
}
22+
23+
/// Returns the greeting as a string.
24+
///
25+
/// # Examples
26+
///
27+
/// ```
28+
/// use hello_lib::greeter::Greeter;
29+
///
30+
/// let greeter = Greeter::new("Hello");
31+
/// let greeting = greeter.greeting("World");
32+
/// ```
33+
pub fn greeting(&self, thing: &str) -> String {
34+
format!("{} {}", &self.greeting, thing)
35+
}
36+
37+
/// Prints the greeting.
38+
///
39+
/// # Examples
40+
///
41+
/// ```
42+
/// use hello_lib::greeter::Greeter;
43+
///
44+
/// let greeter = Greeter::new("Hello");
45+
/// greeter.greet("World");
46+
/// ```
47+
pub fn greet(&self, thing: &str) {
48+
println!("{} {}", &self.greeting, thing);
49+
}
50+
}
51+
52+
#[cfg(test)]
53+
mod test {
54+
use super::Greeter;
55+
56+
#[test]
57+
fn test_greeting() {
58+
let hello = Greeter::new("Hi");
59+
assert_eq!("Hi Rust", hello.greeting("Rust"));
60+
}
61+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#[cfg(test)]
2+
mod tests {
3+
use std::env;
4+
use std::path::PathBuf;
5+
6+
#[test]
7+
fn test_deps_of_crate_and_its_test_are_merged() {
8+
let rust_project_path = PathBuf::from(env::var("RUST_PROJECT_JSON").unwrap());
9+
10+
let content = std::fs::read_to_string(&rust_project_path)
11+
.unwrap_or_else(|_| panic!("couldn't open {:?}", &rust_project_path));
12+
13+
assert!(
14+
content.contains(r#"{"display_name":"greeter_cdylib","root_module":"shared_lib.rs"#),
15+
"expected rust-project.json to contain a rust_shared_library target."
16+
);
17+
assert!(
18+
content.contains(r#"{"display_name":"greeter_staticlib","root_module":"static_lib.rs"#),
19+
"expected rust-project.json to contain a rust_static_library target."
20+
);
21+
}
22+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod greeter;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod greeter;

0 commit comments

Comments
 (0)