-
Notifications
You must be signed in to change notification settings - Fork 214
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
Allow rule aliasing #935
base: master
Are you sure you want to change the base?
Allow rule aliasing #935
Conversation
Codecov Report
@@ Coverage Diff @@
## master #935 +/- ##
==========================================
- Coverage 92.72% 92.71% -0.02%
==========================================
Files 316 316
Lines 20577 20604 +27
==========================================
+ Hits 19081 19103 +22
- Misses 1496 1501 +5
Continue to review full report at Codecov.
|
493b714
to
888ad16
Compare
We might also need configuration. The issue in #902 is not completely hashed out yet. The problem we'd like to solve is
So before we can come to a definitive implementation conclusion, we should discuss if there are other corner cases to consider, how would we like the such aliases define etc. |
"New name" is always the primary name of the rule implementation, right? So assuming If so, translating aliases in a configuration reading code should cover all cases. The rest of codebase wouldn't even know that alias has been used.
Or something like: struct LintRuleAliasDescriptor {
LintRuleId name; // ID/name of the alias.
absl::string_view topic; // section in style-guide
absl::string_view dv_topic; // section in design verification style-guide
std::string desc; // Detailed description
std::vector<std::pair<absl::string_view, absl::string_view>>
param_defaults; // List of param values set by the alias
};
// ...
const std::vector<LintRuleAliasDescriptor>&
UndersizedNumericLiteralRule::GetAliasDescriptors() {
static const std::vector<LintRuleAliasDescriptor> d{
{
.name = "undersized-binary-literal",
// Empty .topic -> the same as the original rule's
// Empty .desc -> something like:
// "Alias for <original_rule_name> with config=<param>:<value>"
.param_defaults =
{
{"bin", "true"},
},
},
};
return d;
}
|
b1a6727
to
23c6f99
Compare
Right now it's legal to use the same rule several times in configuration. You can disable it, enable, disable again, then apply addiontional changes on top of it using the comandline arguments. This is processed in order, the defaults first, then the config file, then the arguments. Should we disallow this (or warn about this) when we introduce aliases? Example case:
It's okay, would work the same as without aliases. Another case:
Now, if we enable the rule again, either by its original name or an alias, should we care about the previously set parameter values? Should we delete them? Of course this case may make no sense in practical view, but as Verible allows to enable and disable rules multiple times, do we need to address this additionally?
Aliases are translated to the original names early, so that there's no need to create double rules and keep track of whether the original one, or the aliased one is enabled or disabled. The name of a rule (printed when Verible finds violations) is stored in a const structure, like this one: In order to implement printing the right name (alias, if alias was used, the original name otherwise) we could change this to variable and overwrite the We could add a field for the name that would actually be printed in logs (like Alternatively, we can store information about which name shall be printed in an additional container, (not in each rule). |
1a17752
to
cd0fa0d
Compare
cd0fa0d
to
b284fbf
Compare
I like this implementation so far. I'll play around with it a bit and report back. |
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 think it got more complicated by having a GetAliasDescriptors()
function. It looks like adding the alias descriptors just to the toplevel descriptor (which can be left uninitialized if a rule does not have an alias) should make it more easy to maintain.
@@ -53,7 +53,7 @@ VERILOG_REGISTER_LINT_RULE(UndersizedBinaryLiteralRule); | |||
|
|||
const LintRuleDescriptor& UndersizedBinaryLiteralRule::GetDescriptor() { | |||
static const LintRuleDescriptor d{ | |||
.name = "undersized-binary-literal", | |||
.name = "undersized-numeric-literal", | |||
.topic = "number-literals", | |||
.desc = | |||
"Checks that the digits of binary literals for the configured " |
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.
For the 'numeric' literal, we should now actually switch all bin
, oct
and hex
to 'true', while the undersized-binary-literal would have bin=true and oct=false, hex=false. That way we can have the advantage of having a good easy-to-discover al lthe features-rule and the limited to what the old binary rule to not surprise existing users-rule.
This would be also the typical application of the aliases: rules evolve and will get more features, but somtimes we don't want to expose these features in a rule that had a very specific name (like in this case where 'binary' kindof indicates that it only deals with one type of number).
So let's have here all features turned on and in the binary rule the ones not bin
turned off.
@@ -53,7 +53,7 @@ VERILOG_REGISTER_LINT_RULE(UndersizedBinaryLiteralRule); | |||
|
|||
const LintRuleDescriptor& UndersizedBinaryLiteralRule::GetDescriptor() { |
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.
We should probably rename the whole class to be UndersizedNumericLiteralRule
, also the naming of the header and test.
This should probably be a separate PR after this is done, so that we don't have too many changes at once.
@@ -43,6 +43,12 @@ struct LintRuleDescriptor { | |||
std::vector<LintConfigParameterDescriptor> param; | |||
}; | |||
|
|||
struct LintRuleAliasDescriptor { | |||
LintRuleId name; // ID/name of the alias. | |||
std::vector<std::pair<absl::string_view, absl::string_view>> |
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.
std::pairs
have somewhat arbitrary first
, second
members, so it is hard to read. Almost always it is better to define a struct for that with a good name. Adds a few lines, but also makes it much more readable in every place it is used.
Maybe we can re-use the name/value thing we have going on in LintRuleConfigParameterDescriptor
, but decompose it to only use the part with name/value in the alias while the base rule has also description
.
So have a little hierarchy (usually, I'd be in favor of composition instead of inheritance, but we already have a bunch of descriptors defined that all would need changing; it is not too bad
struct LintConfigParameterNameValue {
absl::string_view name;
std::string default_value;
};
// The descriptor also has a human readable description of this parameter
struct LintConfigParameterDescriptor : public LintConfigParameterNameValue {
std::string description;
};
Then, replace the pair with our new name/value struct:
struct LintRuleAliasDescriptor {
LintRuleId name; // ID/name of the alias.
std::vector<LintConfigParameterNameValue> param_defaults; // List of param values set by the alias
};
@@ -73,6 +73,20 @@ const LintRuleDescriptor& UndersizedBinaryLiteralRule::GetDescriptor() { | |||
return d; | |||
} | |||
|
|||
const std::vector<LintRuleAliasDescriptor>& |
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.
Instead of having a separate function GetAliasDescriptors()
(which then requires some SFINAE-magic), I suggest to add a new field std::vector<LintRuleAliasDescriptor> aliases
at the end of our struct LintRuleDescriptor
.
That way, everything can be brace-initialized more compactly in one go in the descriptor and we require less support code for the alias rules as we can just look through the existing descriptor if there are aliases.
(Recently I cleaned up the rules that had multiple static functions for their descriptions to just return one descriptor which made things simpler; I'd like to avoid it getting more compilcated again)
This is a proposal of a solution for #902.
With these changes, we can use an alternative name for a rule.
This is how aliases can be defined:
--help_rules=all
prints the aliases for each rule where they exist.When
--help_rules
option is used with a specific name, the result is the same regardless of if the original name or alias was used.