All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codenarc.rule.naming.FieldNameRule.groovy Maven / Gradle / Ivy

There is a newer version: 3.5.0-groovy-4.0
Show newest version
/*
 * Copyright 2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.codenarc.rule.naming

import org.codehaus.groovy.ast.FieldNode
import org.codehaus.groovy.ast.PropertyNode
import org.codenarc.rule.AbstractAstVisitor
import org.codenarc.rule.AbstractAstVisitorRule
import org.codenarc.util.WildcardPattern

import java.lang.reflect.Modifier

/**
 * Rule that verifies that the name of each field matches a regular expression. By default it checks that
 * non-final field names start with a lowercase letter and contains only letters or numbers.
 * By default, final field names start with an uppercase letter and contain only uppercase
 * letters, numbers and underscores.
 * 

* NOTE: This rule checks only regular fields of a class, not properties. In Groovy, * properties are fields declared with no access modifier (public, protected, private). Thus, * this rule only checks fields that specify an access modifier. For naming of regular * properties, see PropertyNameRule. *

* The regex property specifies the default regular expression to validate a field name. * It is required and cannot be null or empty. It defaults to '[a-z][a-zA-Z0-9]*'. *

* The finalRegex property specifies the regular expression to validate final * field names. It is optional and defaults to null, so that final fields that are not * static will be validated using regex. *

* The staticRegex property specifies the regular expression to validate static * field names. It is optional and defaults to null, so that static fields that are * non-final will be validated using regex. *

* The staticFinalRegex property specifies the regular expression to validate static final * field names. It is optional, but defaults to '[A-Z][A-Z0-9_]*'. *

* The privateStaticFinalRegex property specifies the regular expression to validate private static final * field names. It is optional, but defaults to '[A-Z][A-Z0-9_]*'. *

* The order of precedence for the regular expression properties is: privateStaticFinalRegex, staticFinalRegex, * finalRegex, staticRegex and finally regex. In other words, the first * regex in that list matching the modifiers for the field is the one that is applied for the field name validation. *

* The ignoreFieldNames property optionally specifies one or more * (comma-separated) field names that should be ignored (i.e., that should not cause a * rule violation). The name(s) may optionally include wildcard characters ('*' or '?'). * * @author Chris Mair * @author Hamlet D'Arcy */ class FieldNameRule extends AbstractAstVisitorRule { String name = 'FieldName' int priority = 2 String regex = DEFAULT_FIELD_NAME String staticRegex String finalRegex String staticFinalRegex = DEFAULT_CONST_NAME String privateStaticFinalRegex String ignoreFieldNames = 'serialVersionUID' Class astVisitorClass = FieldNameAstVisitor @Override void validate() { assert regex } } class FieldNameAstVisitor extends AbstractAstVisitor { private final Set propertyNames = [] @Override void visitField(FieldNode fieldNode) { if (!isProperty(fieldNode) && !isIgnoredPropertyName(fieldNode)) { def mod = fieldNode.modifiers def re = rule.regex if (Modifier.isStatic(mod)) { re = rule.staticRegex ?: re } if (Modifier.isFinal(mod)) { re = rule.finalRegex ?: re } if ((Modifier.isFinal(mod)) && (Modifier.isStatic(mod))) { re = rule.staticFinalRegex ?: re } if ((Modifier.isFinal(mod)) && Modifier.isStatic(mod) && Modifier.isPrivate(mod)) { re = rule.privateStaticFinalRegex ?: re } if (!(fieldNode.name ==~ re)) { addViolation(fieldNode, "The fieldname $fieldNode.name in class ${fieldNode.owner?.name} does not match ${re.toString()}") } } super.visitField(fieldNode) } @Override void visitProperty(PropertyNode node) { propertyNames << node.name super.visitProperty(node) } private boolean isIgnoredPropertyName(FieldNode node) { new WildcardPattern(rule.ignoreFieldNames, false).matches(node.name) } private boolean isProperty(FieldNode node) { // This assumes that the property node is visited before the (regular) field node propertyNames.contains(node.name) } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy