org.codenarc.rule.formatting.BracesForTryCatchFinallyRule.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of CodeNarc Show documentation
Show all versions of CodeNarc Show documentation
The CodeNarc project provides a static analysis tool for Groovy code.
/*
* Copyright 2011 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 org.codehaus.groovy.ast.stmt.CatchStatement
import org.codehaus.groovy.ast.stmt.TryCatchStatement
import org.codenarc.rule.AbstractAstVisitor
import org.codenarc.rule.AbstractAstVisitorRule
/**
* Checks the location of the opening brace ({) for try statements, the location
* of the 'catch' keyword and corresponding opening braces, and the location of the 'finally'
* keyword and the corresponding opening braces. By default, requires opening braces on the
* same line, but the sameLine property can be set to false to override this.
*
* By default does not validate catch and finally clauses, to turn this on set properties
* validateCatch and validateFinally to true respectively. The catch and finally handling
* defaults to using the sameLine value so if sameLine is true, we expect "} catch(x) {"
* and "} finally {". For fine grained control, use boolean properties catchOnSameLineAsClosingBrace,
* catchOnSameLineAsOpeningBrace, finallyOnSameLineAsClosingBrace, finallyOnSameLineAsOpeningBrace
*
* @author Geli Crick
* @author Hamlet D'Arcy
* @author Matias Bjarland
* @author Chris Mair
*/
class BracesForTryCatchFinallyRule extends AbstractAstVisitorRule {
String name = 'BracesForTryCatchFinally'
int priority = 2
Class astVisitorClass = BracesForTryCatchFinallyAstVisitor
boolean sameLine = true
boolean validateCatch = false
Boolean catchOnSameLineAsClosingBrace
Boolean catchOnSameLineAsOpeningBrace
boolean validateFinally = false
Boolean finallyOnSameLineAsClosingBrace
Boolean finallyOnSameLineAsOpeningBrace
}
class BracesForTryCatchFinallyAstVisitor extends AbstractAstVisitor {
@Override
void visitTryCatchFinally(TryCatchStatement node) {
BracesForTryCatchFinallyRule myRule = rule as BracesForTryCatchFinallyRule
boolean isBraceOnSameLine = node.lineNumber == node.tryStatement.lineNumber
if (myRule.sameLine) {
if (!isBraceOnSameLine) {
addViolation(node, "Opening brace should be on the same line as 'try'")
}
} else {
if (isBraceOnSameLine) {
addViolation(node, "Opening brace should not be on the same line as 'try'")
}
}
visitCatch(myRule, node)
visitFinally(myRule, node)
super.visitTryCatchFinally(node)
}
void visitCatch(BracesForTryCatchFinallyRule myRule, TryCatchStatement node) {
//TODO: Understand AstUtil.isBlock and isFirstVisit and apply them as appropriate to the below block
if (myRule.validateCatch && node.catchStatements) {
//if user has not explicitly set the catch brace settings, 'inherit' them from sameLine
if (myRule.catchOnSameLineAsClosingBrace == null) {
myRule.catchOnSameLineAsClosingBrace = myRule.sameLine
}
if (myRule.catchOnSameLineAsOpeningBrace == null) {
myRule.catchOnSameLineAsOpeningBrace = myRule.sameLine
}
node.catchStatements.each { CatchStatement stmt ->
def srcLine = sourceLineTrimmed(stmt)
if (myRule.catchOnSameLineAsClosingBrace && !srcLine?.contains('}')) {
addViolation(stmt, "'catch' should be on the same line as the closing brace")
} else if (!myRule.catchOnSameLineAsClosingBrace && srcLine?.contains('}')) {
addViolation(stmt, "'catch' should not be on the same line as the closing brace")
}
boolean isBraceOnSameLine = stmt.lineNumber == stmt.code.lineNumber
if (myRule.catchOnSameLineAsOpeningBrace && !isBraceOnSameLine) {
addViolation(stmt, "Opening brace should be on the same line as 'catch'")
} else if (!myRule.catchOnSameLineAsOpeningBrace && isBraceOnSameLine) {
addViolation(stmt, "Opening brace should not be on the same line as 'catch'")
}
}
}
}
void visitFinally(BracesForTryCatchFinallyRule myRule, TryCatchStatement node) {
//TODO: Understand AstUtil.isBlock and isFirstVisit and apply them as appropriate to the below block
//if user has not explicitly set the finally brace settings, 'inherit' them from sameLine
if (myRule.finallyOnSameLineAsClosingBrace == null) {
myRule.finallyOnSameLineAsClosingBrace = myRule.sameLine
}
if (myRule.finallyOnSameLineAsOpeningBrace == null) {
myRule.finallyOnSameLineAsOpeningBrace = myRule.sameLine
}
if (myRule.validateFinally && node.finallyStatement) {
def stmt = node.finallyStatement
def srcLine = sourceLineTrimmed(stmt)
if (myRule.finallyOnSameLineAsClosingBrace && srcLine && !srcLine?.contains('}')) {
addViolation(stmt, "'finally' should be on the same line as the closing brace")
} else if (!myRule.finallyOnSameLineAsClosingBrace && srcLine?.contains('}')) {
addViolation(stmt, "'finally' should not be on the same line as the closing brace")
}
if (myRule.finallyOnSameLineAsOpeningBrace && srcLine && !srcLine?.contains('{')) {
addViolation(stmt, "Opening brace should be on the same line as 'finally'")
} else if (!myRule.catchOnSameLineAsOpeningBrace && srcLine?.contains('}')) {
addViolation(stmt, "Opening brace should not be on the same line as 'finally'")
}
}
}
}