Skip to content

[core] RFC: arbitrary property values with XML binding #973

@oowekyala

Description

@oowekyala

The need

Atm, some rules in the code style category try to enforce a naming convention (eg a suffix) that should be respected by all the subtypes of a type. These are:

  • LocalHomeNamingConvention
  • LocalInterfaceSessionNamingConvention
  • MDBAndSessionBeanNamingConvention
  • RemoteInterfaceNamingConvention
  • RemoteSessionInterfaceNamingConvention
  1. I think they are too specific for PMD
  2. They are all implemented the same way, and it could be nice to abstract that away. PMD itself uses similar conventions of its own, eg the name of all interfaces extending Node should end with "Node"

It would be nice to have one rule to rule them all, which would be configurable. Unfortunately there's no easy way to do that with our current properties.

My initial idea, was to introduce a StringMapProperty, which would have Map<String, String> as its value. We could then mention the conventions we'd like to follow using eg

<property name="typeToRegex" value="n.s.pmd.Node -> .+Node" />

This wouldn't scale to using many conventions, and is fragile and ugly because it depends of the tokenization of a single string value into a full map. Plus, the rule-side API exposes only strings so you have to do the conversions by hand, and there's no type checking/ validity checking at parse time

Moreover, for each convention, we might want to specify whether it applies eg only for concrete classes, only for interfaces, etc. So we'd need a nicer way to enter all that information cleanly in the xml.

One possible answer

My current idea to achieve that is to introduce a new type of property, which can take any object as a value, and whose values you can set using an XML element, binding XML attributes to bean properties. For example (I didn't focus on the schema, we probably should use some other element that value):

<property name="conventions" >
  <value forType="n.s.pmd.lang.ast.Node" regexConvention=".+Node" onInterfaces="true">
  <value forType="n.s.pmd.lang.metrics.Metric" regexConvention=".+Metric" onlyConcreteClasses="true">
</property>

Here each value element creates a new value for the property "conventions", assuming it's a multi-valued property. Each of these values is an object which has setters for properties "forType", "regexConvention", "onInterfaces", "onlyConcreteClasses", and default values for some of these. The rule then receives a list of those objects to work on via the property.

This kind of flexible property would also help many rules be more powerful and expressive, for example, the *NamingConventionsRules could, instead of just having a regex for each convention, allow setting also the minimum and maximum name length, thus superseding ShortClassName, ShortMethodName, ShortVariable and LongVariable with more flexibility. (I assume here that #972 is implemented, since this text was extracted from that issue)

Any ideas how to implement that? I think jaxb might do something similar but I have no first-hand experience with it

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:RFCA drafted proposal on changes to PMD, up for feedback form the team and community

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions