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

org.codenarc.rule.formatting.ClassEndsWithBlankLineRule.groovy Maven / Gradle / Ivy

There is a newer version: 3.5.0-groovy-4.0
Show newest version
/*
 * Copyright 2018 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.formatting

import groovy.transform.Memoized
import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.ast.ClassNode
import org.codenarc.rule.AbstractAstVisitorRule
import org.codenarc.rule.AbstractAstVisitor
import org.codenarc.rule.Violation
import org.codenarc.util.AstUtil

/**
 * Check whether the class ends with a blank line. By default, it enforces that there must be a blank line before
 * the closing class brace, except:
 *   
    *
  • If the class is synthetic (generated)
  • *
  • If the class is empty and is written in a single line
  • *
  • If the class is a Script class
  • *
      *

      * A blank line is defined as any line that does not contain any visible characters. *

      * This rule can be configured with the following properties: *

        *
      • ignoreSingleLineClasses: a boolean property to forbid single line classes. * If it is false, then single line classes are considered a violation. Default value is true
      • *
      • ignoreInnerClasses: a boolean property to ignore inner classes. * If it is false, then inner classes can cause violations. Default value is false.
      • *
      • blankLineRequired: a boolean property to define if there may be a blank line before the closing * class brace. If it is false, the last line before the brace must not be blank. Otherwise, it must be blank. Default * value is true
      • *
          * * @author David Ausín */ class ClassEndsWithBlankLineRule extends AbstractAstVisitorRule { String name = 'ClassEndsWithBlankLine' int priority = 3 boolean ignoreSingleLineClasses = true boolean ignoreInnerClasses = false boolean blankLineRequired = true Class astVisitorClass = ClassEndsWithBlankLineAstVisitor } class ClassEndsWithBlankLineAstVisitor extends AbstractAstVisitor { private static final int PENULTIMATE_LINE_OFFSET = 2 private static final char CLOSE_BRACE_CHARACTER = '}' @Override protected void visitClassComplete(ClassNode classNode) { if (classNode.lineNumber == -1) { return } if (classNode.isScript()) { return } if (classNode.outerClass && rule.ignoreInnerClasses) { return } if (isSingleLineClassViolation() && isSingleLineClass(classNode)) { return } if (rule.blankLineRequired) { checkIfThereIsBlankLineBeforeClosingBrace(classNode) } else { checkIfThereIsNotBlankLineBeforeClosingBrace(classNode) } } private boolean isSingleLineClassViolation() { rule.ignoreSingleLineClasses || !rule.blankLineRequired } private void checkIfThereIsNotBlankLineBeforeClosingBrace(ClassNode classNode) { String trimmedLineBeforeClosingBrace = getPenultimateLine(classNode).trim() String trimmedLineOfClosingBrace = getLastLine(classNode).trim() if (trimmedLineOfClosingBrace == CLOSE_BRACE_CHARACTER && trimmedLineBeforeClosingBrace.isEmpty()) { addViolation(classNode, 'Class ends with an empty line before the closing brace', classNode.getLastLineNumber()) } } private void checkIfThereIsBlankLineBeforeClosingBrace(ClassNode classNode) { if (isSingleLineClass(classNode)) { addViolation(classNode, 'Single line classes are not allowed', classNode.getLastLineNumber()) return } String trimmedLineBeforeClosingBrace = getPenultimateLine(classNode).trim() String trimmedLineOfClosingBrace = getLastLine(classNode).trim() if (trimmedLineOfClosingBrace != CLOSE_BRACE_CHARACTER || !trimmedLineBeforeClosingBrace.isEmpty()) { addViolation(classNode, 'Class does not end with a blank line before the closing brace', classNode.getLastLineNumber()) } } private String getPenultimateLine(ClassNode classNode) { Integer penultimateLastLineNumber = classNode.lastLineNumber - PENULTIMATE_LINE_OFFSET return AstUtil.getRawLine(sourceCode, penultimateLastLineNumber) } private String getLastLine(ClassNode classNode) { return AstUtil.getLastLineOfNodeText(classNode, sourceCode) } @Memoized private Boolean isSingleLineClass(ClassNode classNode) { return AstUtil.getNodeText(classNode, sourceCode) == AstUtil.getLastLineOfNodeText(classNode, sourceCode) } private void addViolation(ASTNode node, String message, int lineNumber) { if (lineNumber >= 0) { String sourceLine = AstUtil.getLastLineOfNodeText(node, getSourceCode()) Violation violation = new Violation() violation.rule = rule violation.lineNumber = lineNumber violation.sourceLine = sourceLine violation.message = message violations.add(violation) } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy