Skip to content

Commit

Permalink
LSP: auto-complete relative to CARGO_MANIFEST_DIR in slint! macro
Browse files Browse the repository at this point in the history
  • Loading branch information
ogoffart committed Jun 26, 2023
1 parent e6cf1a8 commit a9e68c7
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 18 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ All notable changes to this project are documented in this file.

## Unreleased

### General

### Slint Language

### Rust

### C++

### LSP

- Correctly use the CARGO_MANIFEST_DIR as the base for import and image in `slint!` macro


## [1.1.0] - 2023-06-26

### General
Expand Down
42 changes: 26 additions & 16 deletions internal/compiler/typeloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,22 +521,7 @@ impl TypeLoader {
file_to_import: &str,
) -> Option<(PathBuf, Option<&'static [u8]>)> {
// The directory of the current file is the first in the list of include directories.
let maybe_current_directory = match referencing_file {
Some(path) if path.extension().map_or(false, |e| e == "rs") => {
// For .rs file, this is a rust macro, and rust macro locates the file relative to the CARGO_MANIFEST_PATH which is the directory that has a Cargo.toml file.
let mut candidate = path;
loop {
candidate =
if let Some(c) = candidate.parent() { c } else { break path.parent() };
if candidate.join("Cargo.toml").exists() {
break Some(candidate);
}
}
}
Some(path) => path.parent(),
None => None,
}
.map(|p| p.to_path_buf());
let maybe_current_directory = referencing_file.and_then(base_directory);

maybe_current_directory
.clone()
Expand Down Expand Up @@ -625,6 +610,31 @@ impl TypeLoader {
}
}

/// return the base directory from which imports are loaded
///
/// For a .slint file, this is the parent directory.
/// For a .rs file, this is relative to the CARGO_MANIFEST_DIR
///
/// Note: this function is only called for .rs path as part of the LSP or viewer.
/// Because from a proc_macro, we don't actually know the path of the current file, and this
/// is why we must be relative to CARGO_MANIFEST_DIR.
pub fn base_directory(referencing_file: &Path) -> Option<PathBuf> {
if referencing_file.extension().map_or(false, |e| e == "rs") {
// For .rs file, this is a rust macro, and rust macro locates the file relative to the CARGO_MANIFEST_DIR which is the directory that has a Cargo.toml file.
let mut candidate = referencing_file;
loop {
candidate =
if let Some(c) = candidate.parent() { c } else { break referencing_file.parent() };
if candidate.join("Cargo.toml").exists() {
break Some(candidate);
}
}
} else {
referencing_file.parent()
}
.map(|p| p.to_path_buf())
}

#[test]
fn test_dependency_loading() {
let test_source_path: PathBuf =
Expand Down
5 changes: 3 additions & 2 deletions tools/lsp/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,10 +484,11 @@ fn complete_path_in_string(base: &Path, text: &str, offset: u32) -> Option<Vec<C
}
let mut text = text.strip_prefix('\"')?;
text = &text[..(offset - 1) as usize];
let base = i_slint_compiler::typeloader::base_directory(base)?;
let path = if let Some(last_slash) = text.rfind('/') {
base.parent()?.join(Path::new(&text[..last_slash]))
base.join(Path::new(&text[..last_slash]))
} else {
base.parent()?.to_owned()
base
};
let dir = std::fs::read_dir(path).ok()?;
Some(
Expand Down

0 comments on commit a9e68c7

Please sign in to comment.