Skip to content

Commit

Permalink
fix: Go to definition in external repositories (#26)
Browse files Browse the repository at this point in the history
The workspace directory for external repositories is now inferred via
the `DO_NOT_BUILD_HERE` file, if the workspace is not given to the LSP
context.

Fixes #25
  • Loading branch information
cameron-martin authored Feb 25, 2024
1 parent c0c56dc commit e80ba05
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 11 deletions.
34 changes: 28 additions & 6 deletions src/bazel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,20 @@ impl<Client: BazelClient> BazelContext<Client> {
}

/// Gets the possibly-cached workspace for a directory, or creates a new one if it doesn't exist.
/// Returns none if a workspace cannot be found
/// If the workspace is not given, it is inferred based on the current file.
/// Returns None if a workspace cannot be found.
fn workspace<P: AsRef<Path>>(
&self,
workspace_dir: Option<P>,
current_file: &LspUrl,
) -> anyhow::Result<Option<Rc<BazelWorkspace>>> {
let mut workspaces = self.workspaces.borrow_mut();

let workspace_dir = match workspace_dir.as_ref() {
Some(workspace_dir) => Some(Cow::Borrowed(workspace_dir.as_ref())),
None => self.infer_workspace_dir(current_file)?.map(Cow::Owned),
};

if let Some(workspace_dir) = workspace_dir {
if let Some(workspace) = workspaces.get(workspace_dir.as_ref()) {
Ok(Some(workspace.clone()))
Expand All @@ -339,6 +346,21 @@ impl<Client: BazelClient> BazelContext<Client> {
}
}

fn infer_workspace_dir(&self, current_file: &LspUrl) -> io::Result<Option<PathBuf>> {
if let LspUrl::File(path) = current_file {
for dir in path.ancestors().skip(1) {
let file = dir.join("DO_NOT_BUILD_HERE");
if file.exists() {
return Ok(Some(PathBuf::from(fs::read_to_string(file)?)));
}
}

Ok(None)
} else {
Ok(None)
}
}

pub(crate) fn file_with_contents(
&self,
filename: &str,
Expand Down Expand Up @@ -596,7 +618,7 @@ impl<Client: BazelClient> LspContext for BazelContext<Client> {
workspace_root: Option<&Path>,
) -> anyhow::Result<LspUrl> {
let label = Label::parse(path)?;
let workspace = self.workspace(workspace_root)?;
let workspace = self.workspace(workspace_root, current_file)?;

let folder = self.resolve_folder(&label, current_file, workspace.as_deref())?;

Expand Down Expand Up @@ -624,7 +646,7 @@ impl<Client: BazelClient> LspContext for BazelContext<Client> {
current_file: &LspUrl,
workspace_root: Option<&Path>,
) -> anyhow::Result<String> {
let workspace = self.workspace(workspace_root)?;
let workspace = self.workspace(workspace_root, current_file)?;

match (target, current_file) {
// Check whether the target and the current file are in the same package.
Expand Down Expand Up @@ -780,7 +802,7 @@ impl<Client: BazelClient> LspContext for BazelContext<Client> {
current_value: &str,
workspace_root: Option<&Path>,
) -> anyhow::Result<Vec<StringCompletionResult>> {
let workspace = self.workspace(workspace_root)?;
let workspace = self.workspace(workspace_root, document_uri)?;

let offer_repository_names = current_value.is_empty()
|| current_value == "@"
Expand Down Expand Up @@ -906,7 +928,7 @@ mod tests {
let url = context.resolve_load(
"//:foo.bzl",
&LspUrl::File(fixture.external_dir("foo").join("BUILD")),
Some(&fixture.workspace_root()),
None,
)?;

assert_eq!(
Expand All @@ -925,7 +947,7 @@ mod tests {
let url = context.resolve_load(
"@bar//:bar.bzl",
&LspUrl::File(fixture.external_dir("foo").join("BUILD")),
Some(&fixture.workspace_root()),
None,
)?;

assert_eq!(
Expand Down
23 changes: 18 additions & 5 deletions src/test_fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,17 @@ pub struct TestFixture {
}

impl TestFixture {
pub fn new(name: &str) -> io::Result<TestFixture> {
Ok(TestFixture {
pub fn new(name: &str) -> anyhow::Result<TestFixture> {
let fixture = TestFixture {
path: fs::canonicalize(PathBuf::from(".").join("fixtures").join(name))?,
})
};

fs::write(
fixture.output_base().join("DO_NOT_BUILD_HERE"),
path_to_string(fixture.workspace_root())?,
)?;

Ok(fixture)
}

pub fn output_base(&self) -> PathBuf {
Expand Down Expand Up @@ -75,8 +82,14 @@ impl ContextBuilder {
self
}

pub(crate) fn repo_mapping_json(mut self, repo: &str, mapping: serde_json::Value) -> anyhow::Result<Self> {
self.client.repo_mappings.insert(repo.into(), serde_json::from_value(mapping)?);
pub(crate) fn repo_mapping_json(
mut self,
repo: &str,
mapping: serde_json::Value,
) -> anyhow::Result<Self> {
self.client
.repo_mappings
.insert(repo.into(), serde_json::from_value(mapping)?);

Ok(self)
}
Expand Down

0 comments on commit e80ba05

Please sign in to comment.