Skip to content
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

IdentifierName: accept regex to exempt type name violations #4842

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

commonquail
Copy link

@commonquail commonquail commented Feb 25, 2025

Here is an attempt at teaching IdentifierName to allow custom type name patterns that would otherwise be considered (true positive) violations, for use where external factors necessitate a violating form but the existing AllowInitialismsInTypeName is either too accepting or fails to match.

This implementation satisfies the JMX M(X)Bean type name pattern (closes #4776) and the Maven Failsafe plugin filter pattern (closes #4832), however, I consider some of its details contradictory; see notes.

For the new option I'm using the working name of AllowRegexInTypeName, derived from AllowInitialismsInTypeName, but I have reservations about that.

The existence of AllowInitialismsInTypeName is not officially documented anywhere, much less its behavior, so neither is the new option I propose here. That seems to be the norm, too, but I'd be happy to change that.

Occasionally, type names need to follow conventions that violate the
styleguide without being able to rely on inheritance or annotations for
exemption. For example, JMX MBean and MXBean definitions will routinely
violate the styleguide, and outside the JDK, `maven-failsafe-plugin`
3.5.2's default filter is a set of 3 violating patterns. Suppressing
these violations quickly becomes tedious.

Rather than Whac-A-Mole'ing tolerated violations, define a new option
whose value is a regex such that, if a possibly-violating type name
matches that regex, the type name is allowed anyway.

References: google#4776
References: google#4832
@@ -294,7 +299,9 @@ private static boolean isConformantLowerCamelName(String name) {
private boolean isConformantTypeName(String name) {
return !name.contains("_")
&& isUpperCase(name.charAt(0))
&& (allowInitialismsInTypeName || !PROBABLE_INITIALISM.matcher(name).find());
&& (allowInitialismsInTypeName
|| allowRegexInTypeName.matcher(name).matches()
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AllowInitialismsInTypeName reads and works approximately like "allow initialisms [when they occur within a] type name". Similarly, AllowRegexInTypeName reads approximately like "allow [this] regex [when it matches within a] type name." However, I've used the anchored matches() instead of the unanchored find() and that makes me think that either

  1. the option name and this placement are incorrect, or
  2. matches() is incorrect.

When I imagine how I would reason about this functionality, I arrive at "a simple-name that satisfies this pattern should be allowed, even when it would have been rejected". That mental model seems to interact with the fewest other rules and therefore be the simplest and easiest to reason about, but it can also be a blanket pass to ignore every other defined rule and that may be too much flexibility. In any case, to accurately implement that mental model

  1. the new regex should be the first thing we matches(), and only on failure should we proceed to the original checks.
  2. the regex's current fallback match-anything pattern would have to change, perhaps just into a presence/absence form.
  3. the name should probably not use the word "in", which can imply find()-semantics, but be something more like AllowTypeNameMatchingRegex.

A completely different approach is to parameterize PROBABLE_INITIALISM with ~its current value as the default. That grants maximal flexibility, but my objective with this proposal is not to bypass or challenge the styleguide's definition of camel case, only to provide what amounts to a high-level suppression mechanic. I think parameterizing PROBABLE_INITIALISM would be a fair bit more difficult to build and to use, and would grant an escape hatch that is too wide.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For demonstration, a version that more faithfully matches my mental model: master...commonquail:error-prone:identifiername-allow-class-regex-harder. If I had to explain to somebody how this worked, that's the version I would rather explain.

@@ -658,6 +658,21 @@ public void className_underscore() {
.doTest();
}

@Test
public void className_badPattern_allowed() {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Name?
  • Explicit positive case?
  • Interaction with other rules?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

IdentifierName rejects m-failsafe-p default inclusion patterns Allow MXBean in IdentifierName
1 participant