-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Refactor Options
representation
#7591
Conversation
Current dependencies on/for this PR:
This comment was auto-generated by Graphite. |
CodSpeed Performance ReportMerging #7591 will not alter performanceComparing Summary
|
fields.sort_unstable_by(|(name, _), (name2, _)| name.cmp(name2)); | ||
sets.sort_unstable_by(|(name, _), (name2, _)| name.cmp(name2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how I feel about sorting options. It disallows grouping options that are semantically related (all resolver settings)
crates/ruff_workspace/src/options.rs
Outdated
impl OptionsMetadata for FormatOrOutputFormat { | ||
fn record(visit: &mut dyn Visit) { | ||
FormatOptions::record(visit) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also feels less hacky now since we have a trait.
960622f
to
5dc5178
Compare
} | ||
impl Visit for CollectOptionsVisitor { | ||
fn record_set(&mut self, name: &str, group: OptionSet) { | ||
self.groups.push((name.to_owned(), group)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old implementation only supports one level of nesting. This would have become a problem with lint.pydocstyle.option
where we have two level nesting.
PR Check ResultsEcosystem✅ ecosystem check detected no changes. |
bc3127d
to
effaf85
Compare
5dc5178
to
86a61b3
Compare
} | ||
|
||
fn generate_set(output: &mut String, set: &Set) { | ||
writeln!(output, "### {title}\n", title = set.title()).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
writeln!
with trailing \n
looks strange
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree but everything else feels verbose just to get two newlines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I typically do two writeln
for this but don't feel strongly.)
effaf85
to
a5e2a14
Compare
86a61b3
to
2ee6747
Compare
a5e2a14
to
7a13d26
Compare
2ee6747
to
0fe9465
Compare
0fe9465
to
f63df7d
Compare
Summary
This PR refactors the
Options
representation.Current Reprsentation
Our
ConfigureOptions
macro currently generates the following code (truncated):You can see how it generates a static array and
metadata
returns anOptionGroup(&slice)
referring to the slice of the static array.Options can be nested (option-groups). The macro calls into the nested type's
metadata
function to get theOptionGroup
and adds aOptionEntry::Group()
to its static arrayThis works well enough and the API is simple. However, it requires that the macro statically determines all options to be able to set the length of the array.
New Requirements
I'm about to introduce a new
lint
section to the configuration without removing the top-level options until the new configuration is stabilized. The simplest but very verbose approach is duplicating thelint
options: Once at the top level and once under thelint
section. But that's rather verbose. Ideally, I want to use serde'sflatten
feature and write:While serde and schemars support this nicely, our options macro does not, and adding it is impossible with the current representation. The problem is that macros operate on a tokens stream only. They can't resolve types (at least to my knowledge). But that's what's necessary for
Options
to statically determine the length of itsOPTIONS
array: It needs to expand theLintOptions
options intoOptions
.New Representation
The new representation is inspired by serde and
tracing_subscribs
'sVisit
trait.The basic idea is to implement the metadata abstraction as a visitor pass (to avoid allocations).
OptionsMetadata
OptionsMetadata::record
callsrecord_field
orrecord_set
for each optionwhere
Visit
is defined asThis new representation has a few advantages:
OptionsMetadata
trait can be implemented manually for cases where the derive macro isn't flexible enoughOptionsMetadata
provides all relevant abstractions so that the macro is optional. It means you can now understand the system without understanding the macro.flatten
becomes a simpleNested::record(visit)
call (instead of callingvisit.record_set(name, Nested::metadata())
. Meaning we traverse into the sub-set without telling the visitor that it now enters a new set.The main downside of the new API is that writing visitors is awkward. This is evident by the longer implementations for
has
,get
, andDisplay
. I think that's a fair tradeoff, considering that these methods are implemented once and that a similar API is provided to consumers.Test Plan
cargo dev generate-options
produces the exact same outputconfig
command continues working