-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Replace JSONPath with jq
in jsondocck
#143089
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
Replace JSONPath with jq
in jsondocck
#143089
Conversation
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #143337) made this pull request unmergeable. Please resolve the merge conflicts.
(cc @aDotInTheVoid)
Sorry for taking so long to review this. Thanks for working on it, especially the repetitive test migration.
I don't think it'll be a good idea to construct a JSONPath-
jq
transpiler because it'll look really awkward for new contributors
What do you mean by this? The idea was to use the transpiler to migrate all the assertions in the tests, leaving them in jq. New contributors should never need to know it existed.
I expect
jsondocck
to have just 2 directives:jq
andarg
I think this is a quite bad idea. It means we loose any sort of good error reporting. With this PR at the moment, we can only say that a check failed, but not why (in the case that the query matched the wrong value). Having this is really important I think.
it's unnecessary for private crates
the deleted lines are duplicates of the lines 36 & 37
there are no insignificant whitespaces or comments, it's a single line
- directives were collected before processing, but there seems to be nothing preventing them from checking right away - the unified error message style follows the style of short diagnostics from the compiler (almost the same was used on the deleted line 39)
as for the start and end anchors (`^` & `$`), they're unnecessary since we apply this regex to separate lines, not whole text
i tried to keep the original code structure, but it's an almost entire rewrite. thankfully, there are more deletions than insertions, i expect jq to be flexible enough to supersede almost the entire previous set of directives. no tests yet, but it seems to be working. jaq's guts are a bit arcane to me, but it seems to be only related to its setup, a resulted API turned out to be pretty straightforward
b4b23aa
to
97d350d
Compare
The job tidy
failed! Check out the build log: (web) (plain enhanced) (plain)
Click to see the possible cause of the failure (guessed by this bot)
All checks passed!
checking python file formatting
28 files already formatted
checking C++ file formatting
some tidy checks failed
Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:01:20
local time: Thu Jul 10 22:52:06 UTC 2025
network time: 2025年7月10日 22:52:06 GMT
##[error]Process completed with exit code 1.
Post job cleanup.
What do you mean by this? The idea was to use the transpiler to migrate all the assertions in the tests, leaving them in jq. New contributors should never need to know it existed.
Sorry, I somehow thought that you propose to leave tests as is and integrate the transpiler into jsondocck
so that it'll convert all directive every test run. Nevertheless, while your idea to make transpiler for a test migration is great, I think manual migration will look much better and may even catch some mistakes, like I just found in target_feature.rs
:
I think this is a quite bad idea. It means we loose any sort of good error reporting.
I see. I've added 2 directives eq
& ne
. They act like is
& !is
and report what values they received in case of mismatch. You can see how it looks in the attrs/
tests directory. So, in total, arg
, jq
, eq
, and ne
. Would that be enough?
☔ The latest upstream changes (presumably #143810) made this pull request unmergeable. Please resolve the merge conflicts.
I see. I've added 2 directives
eq
&ne
. They act likeis
&!is
and report what values they received in case of mismatch. You can see how it looks in theattrs/
tests directory. So, in total,arg
,jq
,eq
, andne
. Would that be enough?
I don't think this PR needs to change the directives that exist at all to be honest. Why do you think that's the right approach?
What's the benefit of renaming is
/!is
to eq
/ne
(and set
to arg
)? It seems like it's churn for no gain, but maybe I'm missing something.
I think the best approach would be to keep all the existing directives, and not do a general jq
directive. (That behavior could be with something like //@ is '.some.jq.query' true
, but I don't think this should be encouraged). But this is based just on thinking about it, and you've written a load of tests in jq. I'm curious which way you think makes sense, and why.
I think that porting the current directives instead of declaring new ones might confuse devs that got used to how the current directives work since they won't be exactly they same.
For example, I'm not sure whether has
can be ported at all because you can't just check a path existence the same way you do in JSONPath. For nonexistent paths, jq
returns null
, but if an existing path contains null
, you'll get null
, too. Instead, you need to use the special has
function, which defeats the purpose of the has
directive, replacing it with is
/jq
:
// true (if returns any value, null returned in this case) //@ has .non_existent_field // false //@ jq .exisiting_field_with_null // false //@ jq .non_existent_field // a right way //@ is has("exisiting_field_with_null"), true //@ is has("non_existent_field"), false
What I'm also trying to do is shift as much work as possible to jq
, so that there'd be a minimal set of absolutely obvious directives for contributors that are already familiar with jq
without diving into details about using a more appropriate directive instead of using just jq
.
For example, with count
we'd have multiple ways to count matches:
//@ count .some_array_field, 42 //@ is .some_array_field | length, 42
Without - just the last one.
With ismany
, I'd need to get shlex
back along with tons of quotes and have multiple ways to assert objects:
//@ ismany '.index[].inner.static.expr' '""' '""' '""' '""' '""' '""' '""' '""' //@ is '[.index[].inner.static.expr]' '["", "", "", "", "", "", "", ""]'
Without - just the last one.
As some kind of a middle-ground, I can suggest to avoid renaming and port only 3 directives: set
, is
, and !is
. And use
is length, 42
instead ofcount
is [.], [1, 2, 3]
instead ofismany
is has("field")
/is contains(42)
/is ., {"field":42}
instead ofhas
not do a general
jq
directive. (That behavior could be with something like//@ is '.some.jq.query' true
, but I don't think this should be encouraged).
Okay, I'll remove it and use (!)is
instead. jq
is indeed quite generic in comparison to the current directives. And is
can be compacted to automatically assert a value with true, if it has no second argument.
What do you think?
For nonexistent paths,
jq
returnsnull
, but if an existing path containsnull
, you'll getnull
, too
Wah, that's very unfortunate. We should probably ban //@ is .some.path null
, as that's super footgunny. It also messes us 1 argument //@ has .path
(with no value, just checking the path exists).
If we got rid of it completely, what would this look like?
rust/tests/rustdoc-json/path_name.rs
Lines 70 to 73 in 3014e79
is [.], [1, 2, 3]
instead ofismany
This isn't the same semantics. ismany
doens't care about order (#99474).
And
is
can be compacted to automatically assert a value with true, if it has no second argument.
I don't think this is worth it, I'd rather use an explicit true
.
With
ismany
, I'd need to getshlex
back along with tons of quotes and have multiple ways to assert objects:
What are you using to split the jq filter and the values in eq
/ne
now?
This is an ongoing effort to close #142479. I've decided to take a hard path and rewrite
rustdoc-types
's entire testsuite. I don't think it'll be a good idea to construct a JSONPath-jq
transpiler because it'll look really awkward for new contributors, JSONPath's limitations +jaq
's own quirks may create a lot of questions that even current maintainers would've no answers for without digging intojsondocck
's internals.I expect
jsondocck
to have just 2 directives:jq
andarg
. Thanks tojq
's flexibility, these 2 can do everything that the current directive set can and much more (actually, too much, I left some comments to opt out some dependencies when it'll be possible onjaq
's side). I'm trying to actively utilizejq
's features instead of just blindly rewriting existing assertions, so there should be more deletions than additions.When I'll be done, I'll try to rebase and split my work to make it more easier to review. So far
jsondocck
is already functional, so you can check out how it may look like and give some feedback if you want. I'll commit updated tests folder by folder.