⚠️ This page is outdated. Please refer to PMD 7 Tracking Issue #3898 for the current status.
Properties framework 7.0.0 changes7.0.0, with Java 8 and a new ruleset schema, give us an opportunity to largely improve the properties framework. See the advantages.
TOC:
Lambdas give us an opportunity to add validation capabilities to the property descriptors very cleanly. Consider the following interface:
public interface PropertyConstraint<T> extends Predicate<T> { /** * Returns a diagnostic message if the value * has a problem. Otherwise returns an empty * optional. */ default Optional<String> validate(T value) { return pred.test(value) ? Optional.empty() : Optional.of("Constraint violated on value '" + value + "' (" + getConstraintDescription() + ")") } /** * Returns a description of the constraint * imposed by this validator on the values. * E.g. "Should be positive", or "Should be one of A | B | C." * * <p>This is used to generate documentation. * * @return A description of the constraint */ String getConstraintDescription(); }
Add add a method on property builders that can add a constraint of the correct type. Then:
To reduce syntactic overhead, we can have some utility classes return common validators, e.g.
public class NumericConstraints { public static <N extends Number> PropertyConstraint<N> positive() { return PropertyConstraint.fromPredicate(n -> n.intValue() > 0, "Should be positive"); } }New property syntax in XML
See Schema changes
Consequences on the framework's architectureisMultiValue
method of PropertyDescriptor can be removedabstract class PropertyXmlSyntax<E> { E parse(Element elt); Element serialize(E val); // turns this parser into a parser of a collection of elements // i.e. use the parser for the `<value>` elt to parser the `<item>`s of a `<seq>` // This method would be implemented // We can use that to parse properties having as value anything derived from Collection (ie. List, Set, etc), // of any component type provided we already have a parser for it, (this object), and a supplier for actual collection type. final <T extends Collection<? extends E>> PropertyXmlSyntax<T> toSeq(collectionMaker: Supplier<T>) { // not abstract, returns a new PropertySeqSyntax } // plus some methods for documentation }
Deriving subclasses would only be possible within PMD, so that available syntaxes are in a closed set, managed by us.
NOTE: this assumes RulesetFactory uses a DOM parser!! I'm not sure we can modularise this with a SAX parser...
PropertyDescriptor is enriched with the following method:
interface PropertyDescriptor<T> { PropertyXmlSyntax<T> getXmlSyntaxInterface(); }
This method replaces String asDelimitedString(T value)
and T valueFrom(String propertyString)
, which are not general enough anymore
One can define a property for literally any type they want, provided they have a PropertyXmlSyntax for it.
<value>
can accomodate anything, but collections properties may want to use the <seq>
syntax for better readability. Similarly, maps may want to use an alternate map syntax if we introduce one, etc.type()
method of PropertyDescriptor should be dropped. It's used to document the way the value is supposed to be provided, but since generic type arguments are erased, it won't be of use. Rather, the things to document would be the PropertyXmlSyntaxes.IntegerProperty
-> PropertyDescriptor<Integer>
in user codePropertyFactoryClass
. E.g.
new IntegerProperty(...)
or IntegerProperty.named(..)
is replaced by PropertyFactory.intProperty(...)
, which returns a builder.build
method's return type is PropertyDescriptor
The change revolves around two points:
isBlank
on the PropertyDescriptor interface. If it returns true, then defaultValue
's result can be given no meaningful interpretationisBlank
or a defaultValue
Rule.dysfunctionReason
, ensuring the rule is not run and a configuration error is reportedAtm, 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
- I think they are too specific for PMD
- 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.
...
Current rule equality is defined by rule name + language:
So we may have an "abstract" rule with eg the following XPath, modulo some other configuration properties:
//ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[pmd-java:typeIs($superType) and not(matches(@Image, $regexConvention))]And a user could "instantiate" it several times in the same ruleset by referencing it, overriding the name and setting the properties. The only loose point here is that the properties can have no sensible default value, so the best behaviour would be to fail if they're not set IMO. This feature is lacking from the properties framework for now.
We currently deprecate properties by prefixing their name with "deprecated!", which is not cool and error prone. We could add an isDeprecated
method to PropertyDescriptor instead.
We could also allow having name aliases to properties, to greatly reduce the cost of property renaming.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4