Skip to content

Add import layers for testthat files#1260

Open
lionel- wants to merge 3 commits into
oak/salsa-21-multi-targetfrom
oak/salsa-22-testthat
Open

Add import layers for testthat files#1260
lionel- wants to merge 3 commits into
oak/salsa-21-multi-targetfrom
oak/salsa-22-testthat

Conversation

@lionel-

@lionel- lionel- commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Branched from #1259

Whereas scripts in tests/ folders are standalone, scripts in tests/testthat/ are sourced in an environment where:

  • Setup and helper files are run.
  • The package namespace is injected
  • The testthat exports are attached

This PR detects testthat files and adjusts the import layers accordingly, so that symbols injected by testthat are visible in these files.

@lionel- lionel- force-pushed the oak/salsa-21-multi-target branch from 3bba52f to 10b4801 Compare June 11, 2026 12:40
@lionel- lionel- force-pushed the oak/salsa-21-multi-target branch from 10b4801 to a6cc84b Compare June 11, 2026 13:20
@lionel- lionel- force-pushed the oak/salsa-22-testthat branch from 464855a to 0e4fa01 Compare June 11, 2026 13:20

@DavisVaughan DavisVaughan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool

.as_url()
.path_segments()?
.next_back()
.filter(|seg| !seg.is_empty())?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is this because https://example.com/foo/ sees that last / and returns an empty string for the (not really there) segment after the /?

.path_segments()?
.next_back()
.filter(|seg| !seg.is_empty())?;
Some(percent_decode_str(last).decode_utf8_lossy())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

are you sure you dont want decode_utf8().log_err()? given that this already returns an option?

Comment on lines +111 to +112
// at any offset. Only the file's own top-level `library()` calls
// narrow.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

"Only the file's own top-level library() calls"

GROSSSSSSSS, THE HORROR

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LINT THIS?

Comment on lines +161 to +163
/// order (latest-attached first). `before` narrows to a top-level cursor: with
/// `Some(offset)`, keep only file-scope calls that have run by `offset`; with
/// `None`, keep every attach (the end-of-file view, used for lazy contexts).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is the cursor itself top level? not always right? like you can be in a test_that({<cursor>}) block and i wouldnt consider that top level?

i would also appreciate if this comment were rewritten as like a bulleted list of the 2 cases. it was very hard for me to mentally parse with the colon and semicolon

/// 6. base.
///
/// `offset` narrows the components of layer 4. `None` produces the end-of-file
/// view and keeps every `library()` call. `Some(offset)` keeps only the calls

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// view and keeps every `library()` call. `Some(offset)` keeps only the calls
/// view and utilizes every `library()` call. `Some(offset)` utilizes only the calls

"keep" felt like a weird verb here

Comment on lines +305 to +311
fn in_testthat_dir(path: &Utf8Path) -> bool {
let Some(parent) = path.parent() else {
return false;
};
parent.file_name() == Some("testthat") &&
parent.parent().and_then(Utf8Path::file_name) == Some("tests")
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we should upgrade to 2024 edition rust at some point for let chains so you can do things like this

fn in_testthat_dir(path: &Utf8Path) -> bool {
    if let Some(parent) = path.parent() &&
        parent.file_name() == Some("testthat") &&
        let Some(parent) = parent.parent() &&
        parent.file_name() == Some("tests")
    {
        return true
    } else {
        return false
    }
}

/// which currently sorts based on locale, but arguably this should be fixed on
/// the testthat side.
fn testthat_support_key(file: File, db: &dyn Db) -> Cow<'_, str> {
file.path(db).file_name().unwrap_or_default()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What is the default? An empty Owned string i guess? can you just leave it as Option<Cow>? I have no idea if that would sort right

Comment on lines +243 to +244
pkg.set_scripts(&mut db)
.to(vec![helper, setup, test_foo, test_bar]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

i wonder if it will be useful to have a specific field for testthat_scripts or something, so we dont have to tease them apart from regular scripts every time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants