duplicated-name-list

One set of names is written out by hand in several places.

Group
Opportunities
Runs
Runs under ur report: ur report --rule duplicated-name-list
Level
note
Reads
Every file
Fix
None: where the names are declared, and how the lists derive from them, is a design choice

Why

These lists name the same things, compared by their letters and digits so that MaxWidth, max_width, and "max-width" match: a struct's fields or an enum's variants, struct literals that set each field the same way, runs of statements alike but for one name, matches that map each name to a plain value, and arrays of strings. They must change together. Declare the names once, in a table or a macro's input, and derive the rest from it. It reads every language whose grammar states its shapes in a Shapes.rsc; an advisory rule that ur report runs.

The fix, as Ur suggests it: declare the names once and generate each list from that declaration.

For agents

Before listing a set of names again, such as an enum's variants or a struct's fields, look for where they are declared and derive the new list from that.

Example

src/level.rs
pub enum Level {
    Trace,
    Debug,
    Info,
    Warn,
    Error,
}

impl Level {
    pub fn name(&self) -> &'static str {
        match self {
            Level::Trace => "trace",
            Level::Debug => "debug",
            Level::Info => "info",
            Level::Warn => "warn",
            Level::Error => "error",
        }
    }

    pub fn parse(name: &str) -> Option<Level> {
        match name {
            "trace" => Some(Level::Trace),
            "debug" => Some(Level::Debug),
            "info" => Some(Level::Info),
            "warn" => Some(Level::Warn),
            "error" => Some(Level::Error),
            _ => None,
        }
    }
}
What Ur prints
$ ur report --rule duplicated-name-list
opportunity[duplicated-name-list]: 3 lists write out the same 5 names: Trace, Debug, Info, Warn, Error (saves about 9 lines)
  --> ./src/level.rs:1:5-7 variants of `Level`: 5 names
  --> ./src/level.rs:11:9-17 match in `name`: 5 names
  --> ./src/level.rs:21:9-28 match in `parse`: 5 names
  = hint: declare the names once and generate each list from that declaration
1 opportunity saving about 9 lines in all

Try it in the playground →