Skip to content

Add import layers for testthat files#1260

Merged
lionel- merged 4 commits into
mainfrom
oak/salsa-22-testthat
Jun 19, 2026
Merged

Add import layers for testthat files#1260
lionel- merged 4 commits into
mainfrom
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 2 times, most recently 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 /?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yep I've added this comment:

                    // A trailing slash (`.../foo/`) yields a final empty segment,
                    // meaning the URL points at a directory. Drop it so we return
                    // `None` rather than `""`.

Comment thread crates/aether_path/src/file_path.rs Outdated
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?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Possibly, but it feels to me more like Jarl's territory than Oak's.

Comment thread crates/oak_db/src/file_imports.rs Outdated
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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is now:

/// The file's `library()` / `require()` attaches as `Package` layers, in LIFO
/// order (latest-attached first). `before` selects which calls to include:
///
/// - `None`: every attach. The end-of-file view, used for lazy contexts.
/// - `Some(offset)`: only top-level (file-scope) calls that have run by
///   `offset`. Calls nested in a block (e.g. inside `test_that({})`) are
///   dropped, as are calls after the offset.

Comment thread crates/oak_db/src/file_imports.rs Outdated
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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Default but it's unreachable.

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

@lionel- lionel- Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Potentially, but I'd rather have some kind of collation annotation to branch on (via a tracked query).

@lionel- lionel- force-pushed the oak/salsa-21-multi-target branch 5 times, most recently from 688c41f to d06068b Compare June 16, 2026 13:38
@lionel- lionel- force-pushed the oak/salsa-22-testthat branch from 79df227 to cac4c04 Compare June 16, 2026 14:26
@lionel- lionel- force-pushed the oak/salsa-21-multi-target branch from 9252bcc to 934cb90 Compare June 19, 2026 13:56
Base automatically changed from oak/salsa-21-multi-target to main June 19, 2026 13:57
@lionel- lionel- force-pushed the oak/salsa-22-testthat branch from 17a154b to 2ebe7c4 Compare June 19, 2026 13:58
@lionel- lionel- merged commit 8afd86e into main Jun 19, 2026
17 checks passed
@lionel- lionel- deleted the oak/salsa-22-testthat branch June 19, 2026 13:58
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants