Skip to content

added bazel workspace lsp support #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions bazel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "bazel"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
84 changes: 84 additions & 0 deletions bazel/src/bazel_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use std::fmt::Debug;
use std::path::PathBuf;
use std::process::Command;

#[derive(Debug, Clone, PartialEq)]
pub struct BazelInfo {
pub workspace_root: PathBuf,
pub output_base: PathBuf,
pub execroot: PathBuf,
}

fn parse_bazel_info(info: &str) -> Option<BazelInfo> {
let mut workspace_root: Option<PathBuf> = None;
let mut output_base: Option<PathBuf> = None;
let mut execroot: Option<PathBuf> = None;
info.split('\n').for_each(|l| {
let split: Vec<&str> = l.splitn(2, ':').collect();
if split.len() != 2 {
return;
}
let first = split.get(0);
let next = split.get(1);
match (first, next) {
(Some(key), Some(value)) => match key {
&"execution_root" => execroot = Some(value.trim().into()),
&"output_base" => output_base = Some(value.trim().into()),
&"workspace" => workspace_root = Some(value.trim().into()),
_ => {}
},
_ => {}
}
});
match (execroot, output_base, workspace_root) {
(Some(execroot), Some(output_base), Some(workspace_root)) => Some(BazelInfo {
workspace_root,
execroot,
output_base,
}),
_ => {
eprintln!(
"Couldn't find workspace_root, execroot or output_base in output:\n`{}`",
info
);
None
}
}
}

pub fn get_bazel_info(workspace_dir: Option<&str>) -> Option<BazelInfo> {
let mut raw_command = Command::new("bazel");
let mut command = raw_command.arg("info");
command = match workspace_dir {
Some(d) => command.current_dir(d),
None => command,
};

let output = command.output().ok()?;

if !output.status.success() {
return None;
}

let s = std::str::from_utf8(output.stdout.as_slice()).ok()?;

parse_bazel_info(s)
}

#[cfg(test)]
mod tests {
use super::parse_bazel_info;
use super::BazelInfo;

#[test]
fn parses_info() {
assert_eq!(
parse_bazel_info(include_str!("info.txt")),
Some(BazelInfo {
workspace_root: "/home/user/dev/bazel/bazel".into(),
execroot: "/home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel".into(),
output_base: "/home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf".into()
})
)
}
}
23 changes: 23 additions & 0 deletions bazel/src/info.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
bazel-bin: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel/bazel-out/k8-fastbuild/bin
bazel-genfiles: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel/bazel-out/k8-fastbuild/bin
bazel-testlogs: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel/bazel-out/k8-fastbuild/testlogs
character-encoding: file.encoding = ISO-8859-1, defaultCharset = ISO-8859-1
command_log: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/command.log
committed-heap-size: 418MB
execution_root: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel
gc-count: 11
gc-time: 42ms
install_base: /home/user/.cache/bazel/_bazel_user/install/41b71f1bb3ce13f20cfeeb31a9357113
java-home: /home/user/.cache/bazel/_bazel_user/install/41b71f1bb3ce13f20cfeeb31a9357113/embedded_tools/jdk
java-runtime: OpenJDK Runtime Environment (build 11.0.6+10-LTS) by Azul Systems, Inc.
java-vm: OpenJDK 64-Bit Server VM (build 11.0.6+10-LTS, mixed mode) by Azul Systems, Inc.
max-heap-size: 4175MB
output_base: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf
output_path: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel/bazel-out
package_path: %workspace%
release: release 5.2.0
repository_cache: /home/user/.cache/bazel/_bazel_user/cache/repos/v1
server_log: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/java.log.home.user.log.java.20220821-211440.206313
server_pid: 206313
used-heap-size: 266MB
workspace: /home/user/dev/bazel/bazel
118 changes: 118 additions & 0 deletions bazel/src/label.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@

use std::path::PathBuf;

use crate::bazel_info::BazelInfo;

pub struct ExternalLabel {
repository: String,
package: String,
target: String,
}
pub struct LocalLabel {
package: String,
target: String,
}

pub struct RelativeLabel {
sub_package: String,
target: String,
}

pub enum Label {
External(ExternalLabel),
Local(LocalLabel),
Relative(RelativeLabel),
}

impl Label {
fn split_package_target(label: &str) -> Option<(&str, &str)> {
let mut split_parts = label.split(":");
let package = split_parts.next()?;
let target = split_parts.next()?;
Some((package, target))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, //foo can be used as a short-hand for //foo:foo,
and relative labels can skip the :, e.g. foo instead of :foo.

}

fn split_repository_package_target(label: &str) -> Option<(&str, &str, &str)> {
let mut split_parts = label.split("//");
let repository = split_parts.next()?;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And @foo as a short-hand for @foo//:foo.

let package_target = split_parts.next()?;
let (package, target) = Self::split_package_target(package_target)?;
Some((repository, package, target))
}

pub fn replace_fake_file_with_build_target(fake_file: PathBuf) -> Option<PathBuf> {
if fake_file.exists() {
return Some(fake_file);
}
fake_file.parent().and_then(|p| {
let build = p.join("BUILD");
let build_bazel = p.join("BUILD.bazel");
if build.exists() {
Some(build)
} else if build_bazel.exists() {
Some(build_bazel)
} else {
None
}
})
}

pub fn resolve(
self,
bazel_info: &BazelInfo,
current_file_dir: Option<PathBuf>,
) -> Option<PathBuf> {
// TODO: support nested workspaces either by getting info again or at the start getting the info for all the workspaces in the directory
match self {
Label::External(l) => {
let execroot_dirname = bazel_info.execroot.file_name()?;

if l.repository == execroot_dirname.to_str()? {
Some(bazel_info.workspace_root.join(l.package).join(l.target))
} else {
Some(
bazel_info
.output_base
.join("external")
.join(l.repository)
.join(l.package)
.join(l.target),
)
}
}
Label::Local(l) => Some(bazel_info.workspace_root.join(l.package).join(l.target)),
Label::Relative(l) => {
current_file_dir.and_then(|d| Some(d.join(l.sub_package).join(l.target)))
}
}
}

pub fn new(label: &str) -> Option<Self> {
if !label.contains(":") {
return None;
}

if label.starts_with("@") {
let (repository, package, target) =
Self::split_repository_package_target(label.trim_start_matches('@'))?;
return Some(Label::External(ExternalLabel {
repository: repository.to_owned(),
package: package.to_owned(),
target: target.to_owned(),
}));
}
if label.starts_with("//") {
let (package, target) = Self::split_package_target(label.trim_start_matches("//"))?;
return Some(Label::Local(LocalLabel {
package: package.to_owned(),
target: target.to_owned(),
}));
}

let (package, target) = Self::split_package_target(label)?;
Some(Label::Relative(RelativeLabel {
sub_package: package.to_owned(),
target: target.to_owned(),
}))
}
}
2 changes: 2 additions & 0 deletions bazel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod bazel_info;
pub mod label;
1 change: 1 addition & 0 deletions starlark/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ either = "1.6.1"
static_assertions = "1.1.0"
memoffset = "0.6.4"
thiserror = "1.0.30"
bazel = { version = "0.1.0", path = "../bazel" }
starlark_derive = { version = "0.9.0-pre", path = "../starlark_derive" }
starlark_map = { version = "0.9.0-pre", path = "../starlark_map" }
gazebo.version = "0.8.0"
Expand Down
Loading