http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRule.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRule.java new file mode 100644 index 0000000..6d0da0f --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRule.java @@ -0,0 +1,1164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.logging.Logger; + +import com.adobe.ac.pmd.IFlexViolation; +import com.adobe.ac.pmd.nodes.IAttribute; +import com.adobe.ac.pmd.nodes.IClass; +import com.adobe.ac.pmd.nodes.IConstant; +import com.adobe.ac.pmd.nodes.IFunction; +import com.adobe.ac.pmd.nodes.INode; +import com.adobe.ac.pmd.nodes.IPackage; +import com.adobe.ac.pmd.parser.IParserNode; +import com.adobe.ac.pmd.parser.NodeKind; +import com.adobe.ac.utils.StackTraceUtils; + +/** + * Abstract class for AST-based rule Extends this class if your rule is only + * detectable in an AS script block, which can be converted into an Abstract + * Syntax Tree. Then you will be able to either use the visitor pattern, or to + * iterate from the package node, in order to find your violation(s). + * + * @author xagnetti + */ +public abstract class AbstractAstFlexRule extends AbstractFlexRule implements IFlexAstRule +{ + /** + * + */ + protected enum FunctionType + { + GETTER, NORMAL, SETTER + } + + /** + * + */ + protected enum VariableOrConstant + { + CONSTANT, VARIABLE + } + + /** + * + */ + protected enum VariableScope + { + IN_CLASS, IN_FUNCTION + } + + private interface ExpressionVisitor + { + void visitExpression( final IParserNode ast ); + } + + private static final Logger LOGGER = Logger.getLogger( AbstractAstFlexRule.class.getName() ); + + /** + * @param functionNode + * @return + */ + /** + * @param functionNode + * @return + */ + protected static IParserNode getNameFromFunctionDeclaration( final IParserNode functionNode ) + { + IParserNode nameChild = null; + + for ( final IParserNode child : functionNode.getChildren() ) + { + if ( child.is( NodeKind.NAME ) ) + { + nameChild = child; + break; + } + } + return nameChild; + } + + /** + * @param fieldNode + * @return + */ + protected static IParserNode getTypeFromFieldDeclaration( final IParserNode fieldNode ) + { + return fieldNode.getChild( 0 ).getChild( 1 ); + } + + private final List< IFlexViolation > violations; + + /** + * + */ + public AbstractAstFlexRule() + { + super(); + + violations = new ArrayList< IFlexViolation >(); + } + + /* + * (non-Javadoc) + * @see + * com.adobe.ac.pmd.rules.core.AbstractFlexRule#isConcernedByTheCurrentFile + * () + */ + @Override + public boolean isConcernedByTheCurrentFile() + { + return true; + } + + /** + * @param function + * @return the added violation positioned on the given function node + */ + protected final IFlexViolation addViolation( final IFunction function ) + { + final IParserNode name = getNameFromFunctionDeclaration( function.getInternalNode() ); + + return addViolation( name, + name, + name.getStringValue() ); + } + + /** + * @param function + * @param messageToReplace + * @return + */ + protected final IFlexViolation addViolation( final IFunction function, + final String messageToReplace ) + { + final IParserNode name = getNameFromFunctionDeclaration( function.getInternalNode() ); + + return addViolation( name, + name, + messageToReplace ); + } + + /** + * @param violatingNode + * @return the added violation replacing the threshold value in the message + * if any. + */ + protected final IFlexViolation addViolation( final INode violatingNode ) + { + return addViolation( violatingNode.getInternalNode(), + violatingNode.getInternalNode() ); + } + + /** + * @param violatingNode + * @return the added violation replacing the threshold value in the message + * if any. + */ + protected final IFlexViolation addViolation( final INode violatingNode, + final String... messageToReplace ) + { + return addViolation( violatingNode.getInternalNode(), + violatingNode.getInternalNode(), + messageToReplace ); + } + + /** + * @param violatingNode + * @param endNode + * @return the added violation replacing the threshold value in the message + * if any. + */ + protected final IFlexViolation addViolation( final IParserNode violatingNode ) + { + return addViolation( violatingNode, + violatingNode ); + } + + /** + * @param beginningNode + * @param endNode + * @param messageToReplace + * @return the add violation replacing the {0} token by the specified message + */ + protected final IFlexViolation addViolation( final IParserNode beginningNode, + final IParserNode endNode, + final String... messageToReplace ) + { + if ( isAlreadyViolationAdded( beginningNode ) ) + { + return null; + } + final IFlexViolation violation = addViolation( ViolationPosition.create( beginningNode.getLine(), + endNode.getLine(), + beginningNode.getColumn(), + endNode.getColumn() ) ); + + for ( int i = 0; i < messageToReplace.length; i++ ) + { + violation.replacePlaceholderInMessage( messageToReplace[ i ], + i ); + } + + return violation; + } + + /** + * @param violatingNode + * @param endNode + * @param messageToReplace + * @return the add violation replacing the {0} token by the specified message + */ + protected final IFlexViolation addViolation( final IParserNode violatingNode, + final String... messageToReplace ) + { + return addViolation( violatingNode, + violatingNode, + messageToReplace ); + } + + /** + * @param violationPosition + * @return the added violation positioned at the given position + */ + protected final IFlexViolation addViolation( final ViolationPosition violationPosition ) + { + return addViolation( violations, + violationPosition ); + } + + /** + * find the violations list from the given class node + * + * @param classNode + */ + protected void findViolations( final IClass classNode ) + { + findViolationsFromAttributes( classNode.getAttributes() ); + findViolationsFromConstants( classNode.getConstants() ); + findViolations( classNode.getFunctions() ); + if ( classNode.getConstructor() != null ) + { + findViolationsFromConstructor( classNode.getConstructor() ); + } + } + + /** + * find violations in every function in a class + * + * @param function + */ + protected void findViolations( final IFunction function ) + { + } + + /** + * Override this method if you need to find violations from the package ( or + * any subsequent node like class or function) + * + * @param packageNode + */ + protected void findViolations( final IPackage packageNode ) + { + final IClass classNode = packageNode.getClassNode(); + + if ( classNode != null ) + { + findViolations( classNode ); + } + } + + /** + * find the violations list from the given functions list + * + * @param functions + */ + protected void findViolations( final List< IFunction > functions ) + { + for ( final IFunction function : functions ) + { + findViolations( function ); + } + } + + /** + * find the violations list from the given class variables list + * + * @param variables + */ + protected void findViolationsFromAttributes( final List< IAttribute > variables ) + { + } + + /** + * find the violations list from the given class constants list + * + * @param constants + */ + protected void findViolationsFromConstants( final List< IConstant > constants ) + { + } + + /** + * find the violations list from the given class constructor node + * + * @param constructor + */ + protected void findViolationsFromConstructor( final IFunction constructor ) + { + } + + /** + * Find violations in the current file + */ + @Override + protected final List< IFlexViolation > findViolationsInCurrentFile() + { + try + { + if ( getCurrentPackageNode() != null ) + { + visitCompilationUnit( getCurrentPackageNode().getInternalNode() ); + findViolations( getCurrentPackageNode() ); + } + } + catch ( final Exception e ) + { + LOGGER.warning( "on " + + getCurrentFile().getFilePath() ); + LOGGER.warning( StackTraceUtils.print( e ) ); + } + final List< IFlexViolation > copy = new ArrayList< IFlexViolation >( violations ); + + violations.clear(); + + return copy; + } + + /** + * @param statementNode + */ + protected void visitAs( final IParserNode statementNode ) + { + } + + /** + * @param catchNode + */ + protected void visitCatch( final IParserNode catchNode ) + { + visitNameTypeInit( catchNode.getChild( 0 ) ); + visitBlock( catchNode.getChild( 1 ) ); + } + + /** + * @param classNode + */ + protected void visitClass( final IParserNode classNode ) + { + IParserNode content = null; + for ( final IParserNode node : classNode.getChildren() ) + { + if ( node.is( NodeKind.CONTENT ) ) + { + content = node; + break; + } + } + visitClassContent( content ); + } + + /** + * Visit the condition of a if, while, ... + * + * @param condition + */ + protected void visitCondition( final IParserNode condition ) + { + visitExpression( condition ); + } + + /** + * @param doNode + */ + protected void visitDo( final IParserNode doNode ) + { + visitBlock( doNode.getChild( 0 ) ); + visitCondition( doNode.getChild( 1 ) ); + } + + /** + * @param ifNode + */ + protected void visitElse( final IParserNode ifNode ) + { + visitBlock( ifNode.getChild( 2 ) ); + } + + /** + * Visit empty statement + * + * @param statementNode + */ + protected void visitEmptyStatetement( final IParserNode statementNode ) + { + } + + /** + * @param finallyNode + */ + protected void visitFinally( final IParserNode finallyNode ) + { + if ( isNodeNavigable( finallyNode ) ) + { + visitBlock( finallyNode.getChild( 0 ) ); + } + } + + /** + * @param forNode + */ + protected void visitFor( final IParserNode forNode ) + { + visitBlock( forNode.getChild( 3 ) ); + } + + /** + * @param foreachNode + */ + protected void visitForEach( final IParserNode foreachNode ) + { + visitBlock( foreachNode.getChild( 2 ) ); + } + + /** + * @param functionNode + * @param type + */ + protected void visitFunction( final IParserNode functionNode, + final FunctionType type ) + { + final Iterator< IParserNode > iterator = functionNode.getChildren().iterator(); + IParserNode currentNode = iterator.next(); + + while ( currentNode.is( NodeKind.META_LIST ) + || currentNode.is( NodeKind.MOD_LIST ) || currentNode.is( NodeKind.AS_DOC ) + || currentNode.is( NodeKind.MULTI_LINE_COMMENT ) ) + { + currentNode = iterator.next(); + } + currentNode = iterator.next(); + visitParameters( currentNode ); + currentNode = iterator.next(); + visitFunctionReturnType( currentNode ); + try + { + // Intrinsic functions in AS2 + currentNode = iterator.next(); + visitFunctionBody( currentNode ); + } + catch ( final NoSuchElementException e ) + { + } + } + + /** + * @param functionReturnTypeNode + */ + protected void visitFunctionReturnType( final IParserNode functionReturnTypeNode ) + { + visitBlock( functionReturnTypeNode ); + } + + /** + * @param ifNode + */ + protected void visitIf( final IParserNode ifNode ) + { + visitCondition( ifNode.getChild( 0 ) ); + visitThen( ifNode ); + if ( ifNode.numChildren() == 3 ) + { + visitElse( ifNode ); + } + } + + /** + * @param interfaceNode + */ + protected void visitInterface( final IParserNode interfaceNode ) + { + } + + /** + * @param methodCallNode + */ + protected void visitMethodCall( final IParserNode methodCallNode ) + { + final Iterator< IParserNode > iterator = methodCallNode.getChildren().iterator(); + visitExpression( iterator.next() ); + do + { + visitExpressionList( iterator.next() ); + } + while ( iterator.hasNext() ); + } + + /** + * @param newExpression + */ + protected void visitNewExpression( final IParserNode newExpression ) + { + visitExpression( newExpression.getChild( 0 ) ); + visitExpressionList( newExpression.getChild( 1 ) ); + } + + protected void visitOperator( final IParserNode statementNode ) + { + } + + /** + * @param functionParametersNode + */ + protected void visitParameters( final IParserNode functionParametersNode ) + { + if ( isNodeNavigable( functionParametersNode ) ) + { + for ( final IParserNode node2 : functionParametersNode.getChildren() ) + { + visitNameTypeInit( node2.getChild( 0 ) ); + } + } + } + + protected void visitRelationalExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.RELATION, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitShiftExpression( ast ); + } + } ); + } + + /** + * @param ast + */ + protected void visitReturn( final IParserNode ast ) + { + if ( isNodeNavigable( ast ) ) + { + visitExpression( ast.getChild( 0 ) ); + } + } + + /** + * @param statementNode + */ + protected void visitStatement( final IParserNode statementNode ) + { + switch ( statementNode.getId() ) + { + case OP: + visitOperator( statementNode ); + break; + case AS: + visitAs( statementNode ); + break; + case RETURN: + visitReturn( statementNode ); + break; + case IF: + visitIf( statementNode ); + break; + case FOR: + visitFor( statementNode ); + break; + case FOREACH: + visitForEach( statementNode ); + break; + case DO: + visitDo( statementNode ); + break; + case WHILE: + visitWhile( statementNode ); + break; + case SWITCH: + visitSwitch( statementNode ); + break; + case TRY: + visitTry( statementNode ); + break; + case CATCH: + visitCatch( statementNode ); + break; + case FINALLY: + visitFinally( statementNode ); + break; + case STMT_EMPTY: + visitEmptyStatetement( statementNode ); + break; + case LEFT_CURLY_BRACKET: + visitBlock( statementNode ); + break; + default: + visitExpressionList( statementNode ); + } + } + + /** + * @param switchNode + */ + protected void visitSwitch( final IParserNode switchNode ) + { + final Iterator< IParserNode > iterator = switchNode.getChildren().iterator(); + + visitExpression( iterator.next() ); + + final IParserNode cases = iterator.next(); + + for ( final IParserNode caseNode : cases.getChildren() ) + { + final IParserNode child = caseNode.getChild( 0 ); + + if ( child.is( NodeKind.DEFAULT ) ) + { + visitSwitchDefaultCase( caseNode.getChild( 1 ) ); + } + else + { + visitSwitchCase( caseNode.getChild( 1 ) ); + visitExpression( child ); + } + } + } + + /** + * @param switchCaseNode + */ + protected void visitSwitchCase( final IParserNode switchCaseNode ) + { + visitBlock( switchCaseNode ); + } + + /** + * @param defaultCaseNode + */ + protected void visitSwitchDefaultCase( final IParserNode defaultCaseNode ) + { + visitBlock( defaultCaseNode ); + } + + /** + * @param ifNode + */ + protected void visitThen( final IParserNode ifNode ) + { + visitBlock( ifNode.getChild( 1 ) ); + } + + /** + * @param ast + */ + protected void visitTry( final IParserNode ast ) + { + visitBlock( ast.getChild( 0 ) ); + } + + /** + * @param node + */ + protected void visitVariableInitialization( final IParserNode node ) + { + visitExpression( node ); + } + + /** + * @param variableNode + * @param varOrConst + * @param scope + */ + protected void visitVarOrConstList( final IParserNode variableNode, + final VariableOrConstant varOrConst, + final VariableScope scope ) + { + final Iterator< IParserNode > iterator = variableNode.getChildren().iterator(); + + IParserNode node = iterator.next(); + while ( node.is( NodeKind.META_LIST ) + || node.is( NodeKind.MOD_LIST ) ) + { + node = iterator.next(); + } + while ( node != null ) + { + visitNameTypeInit( node ); + node = iterator.hasNext() ? iterator.next() + : null; + } + } + + /** + * @param whileNode + */ + protected void visitWhile( final IParserNode whileNode ) + { + visitCondition( whileNode.getChild( 0 ) ); + visitBlock( whileNode.getChild( 1 ) ); + } + + private boolean isAlreadyViolationAdded( final IParserNode nodeToBeAdded ) + { + for ( final IFlexViolation violation : violations ) + { + if ( violation.getBeginLine() == nodeToBeAdded.getLine() + && violation.getBeginColumn() == nodeToBeAdded.getColumn() ) + { + return true; + } + } + return false; + } + + private boolean isNodeNavigable( final IParserNode node ) + { + return node != null + && node.numChildren() != 0; + } + + private void visitAdditiveExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.ADD, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitMultiplicativeExpression( ast ); + } + } ); + } + + private void visitAndExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.AND, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitBitwiseOrExpression( ast ); + } + } ); + } + + private void visitArrayAccessor( final IParserNode ast ) + { + final Iterator< IParserNode > iterator = ast.getChildren().iterator(); + visitExpression( iterator.next() ); + do + { + visitExpression( iterator.next() ); + } + while ( iterator.hasNext() ); + } + + private void visitBitwiseAndExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.B_AND, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitEqualityExpression( ast ); + } + } ); + } + + private void visitBitwiseOrExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.B_OR, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitBitwiseXorExpression( ast ); + } + } ); + } + + private void visitBitwiseXorExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.B_XOR, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitBitwiseAndExpression( ast ); + } + } ); + } + + private void visitBlock( final IParserNode ast ) + { + if ( isNodeNavigable( ast ) ) + { + for ( final IParserNode node : ast.getChildren() ) + { + visitStatement( node ); + } + } + else if ( ast != null ) + { + visitStatement( ast ); + } + } + + private void visitClassContent( final IParserNode ast ) + { + if ( isNodeNavigable( ast ) ) + { + for ( final IParserNode node : ast.getChildren() ) + { + if ( node.is( NodeKind.VAR_LIST ) ) + { + visitVarOrConstList( node, + VariableOrConstant.VARIABLE, + VariableScope.IN_CLASS ); + } + else if ( node.is( NodeKind.CONST_LIST ) ) + { + visitVarOrConstList( node, + VariableOrConstant.CONSTANT, + VariableScope.IN_CLASS ); + } + } + for ( final IParserNode node : ast.getChildren() ) + { + if ( node.is( NodeKind.FUNCTION ) ) + { + visitFunction( node, + FunctionType.NORMAL ); + } + else if ( node.is( NodeKind.SET ) ) + { + visitFunction( node, + FunctionType.SETTER ); + } + else if ( node.is( NodeKind.GET ) ) + { + visitFunction( node, + FunctionType.GETTER ); + } + } + } + } + + private void visitCompilationUnit( final IParserNode ast ) + { + for ( final IParserNode node : ast.getChildren() ) + { + if ( node.is( NodeKind.PACKAGE ) + && node.numChildren() >= 2 ) + { + visitPackageContent( node.getChild( 1 ) ); + } + if ( !node.is( NodeKind.PACKAGE ) + && node.numChildren() > 0 ) + { + visitPackageContent( node ); + } + } + } + + private void visitConditionalExpression( final IParserNode ast ) + { + if ( ast != null ) + { + if ( ast.is( NodeKind.CONDITIONAL ) ) + { + final Iterator< IParserNode > iterator = ast.getChildren().iterator(); + final IParserNode node = iterator.next(); + + visitOrExpression( node ); + + while ( iterator.hasNext() ) + { + visitExpression( iterator.next() ); + visitExpression( iterator.next() ); + } + } + else + { + visitOrExpression( ast ); + } + } + } + + private void visitEqualityExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.EQUALITY, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitRelationalExpression( ast ); + } + } ); + } + + private void visitExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.ASSIGN, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitConditionalExpression( ast ); + } + } ); + } + + private void visitExpression( final IParserNode ast, + final NodeKind kind, + final ExpressionVisitor visitor ) + { + if ( ast.is( kind ) ) + { + final Iterator< IParserNode > iterator = ast.getChildren().iterator(); + final IParserNode node = iterator.next(); + + visitor.visitExpression( node ); + + while ( iterator.hasNext() ) + { + iterator.next(); + visitor.visitExpression( iterator.next() ); + } + } + else + { + visitor.visitExpression( ast ); + } + } + + private void visitExpressionList( final IParserNode ast ) + { + if ( isNodeNavigable( ast ) ) + { + for ( final IParserNode node : ast.getChildren() ) + { + visitExpression( node ); + } + } + } + + private void visitFunctionBody( final IParserNode node ) + { + visitBlock( node ); + } + + private void visitMultiplicativeExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.MULTIPLICATION, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitUnaryExpression( ast ); + } + } ); + } + + private void visitNameTypeInit( final IParserNode ast ) + { + if ( ast != null + && ast.numChildren() != 0 ) + { + final Iterator< IParserNode > iterator = ast.getChildren().iterator(); + IParserNode node; + + iterator.next(); + iterator.next(); + + if ( iterator.hasNext() ) + { + node = iterator.next(); + visitVariableInitialization( node ); + } + } + } + + private void visitObjectInitialization( final IParserNode ast ) + { + if ( isNodeNavigable( ast ) ) + { + for ( final IParserNode node : ast.getChildren() ) + { + visitExpression( node.getChild( 1 ) ); + } + } + } + + private void visitOrExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.OR, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitAndExpression( ast ); + } + } ); + } + + private void visitPackageContent( final IParserNode ast ) + { + if ( isNodeNavigable( ast ) ) + { + for ( final IParserNode node : ast.getChildren() ) + { + if ( node.is( NodeKind.CLASS ) ) + { + visitClass( node ); + } + else if ( node.is( NodeKind.INTERFACE ) ) + { + visitInterface( node ); + } + } + } + } + + private void visitPrimaryExpression( final IParserNode ast ) + { + if ( ast.is( NodeKind.NEW ) ) + { + visitNewExpression( ast ); + } + else if ( ast.numChildren() != 0 + && ast.is( NodeKind.ARRAY ) ) + { + visitExpressionList( ast ); + } + else if ( ast.is( NodeKind.OBJECT ) ) + { + visitObjectInitialization( ast ); + } + else if ( ast.is( NodeKind.E4X_ATTR ) ) + { + final IParserNode node = ast.getChild( 0 ); + + if ( !node.is( NodeKind.NAME ) + && !node.is( NodeKind.STAR ) ) + { + visitExpression( node ); + } + } + else + { + visitExpressionList( ast ); + } + } + + private void visitShiftExpression( final IParserNode ast ) + { + visitExpression( ast, + NodeKind.SHIFT, + new ExpressionVisitor() + { + public void visitExpression( final IParserNode ast ) + { + visitAdditiveExpression( ast ); + } + } ); + } + + private void visitUnaryExpression( final IParserNode ast ) + { + switch ( ast.getId() ) + { + case PRE_INC: + case PRE_DEC: + case MINUS: + case PLUS: + visitUnaryExpression( ast.getChild( 0 ) ); + break; + default: + visitUnaryExpressionNotPlusMinus( ast ); + } + } + + private void visitUnaryExpressionNotPlusMinus( final IParserNode ast ) + { + switch ( ast.getId() ) + { + case DELETE: + case VOID: + case TYPEOF: + case NOT: + case B_NOT: + visitExpression( ast.getChild( 0 ) ); + break; + default: + visitUnaryPostfixExpression( ast ); + } + } + + private void visitUnaryPostfixExpression( final IParserNode ast ) + { + switch ( ast.getId() ) + { + case ARRAY_ACCESSOR: + visitArrayAccessor( ast ); + break; + case DOT: + case E4X_FILTER: + visitExpression( ast.getChild( 0 ) ); + visitExpression( ast.getChild( 1 ) ); + break; + case POST_INC: + case POST_DEC: + visitPrimaryExpression( ast.getChild( 0 ) ); + break; + case CALL: + visitMethodCall( ast ); + break; + case E4X_STAR: + visitExpression( ast.getChild( 0 ) ); + break; + default: + visitPrimaryExpression( ast ); + break; + } + } +}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRuleTest.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRuleTest.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRuleTest.java new file mode 100644 index 0000000..35aa5e6 --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRuleTest.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.adobe.ac.pmd.IFlexViolation; +import com.adobe.ac.pmd.files.IAs3File; +import com.adobe.ac.pmd.files.IFlexFile; +import com.adobe.ac.pmd.files.IMxmlFile; +import com.adobe.ac.pmd.nodes.IPackage; +import com.adobe.ac.pmd.nodes.impl.NodeFactory; +import com.adobe.ac.pmd.parser.IAS3Parser; +import com.adobe.ac.pmd.parser.exceptions.TokenException; + +import de.bokelberg.flex.parser.AS3Parser; + +public abstract class AbstractAstFlexRuleTest extends AbstractFlexRuleTest +{ + @Override + protected List< IFlexViolation > processFile( final String resourcePath ) throws IOException, + TokenException + { + if ( !getIgnoreFiles().contains( resourcePath ) ) + { + final IAS3Parser parser = new AS3Parser(); + final IFlexFile file = getTestFiles().get( resourcePath ); + + IPackage rootNode = null; + + if ( file == null ) + { + throw new IOException( resourcePath + + " is not found" ); + } + if ( file instanceof IAs3File ) + { + rootNode = NodeFactory.createPackage( parser.buildAst( file.getFilePath() ) ); + } + else + { + rootNode = NodeFactory.createPackage( parser.buildAst( file.getFilePath(), + ( ( IMxmlFile ) file ).getScriptBlock() ) ); + } + return getRule().processFile( file, + rootNode, + getTestFiles() ); + } + return new ArrayList< IFlexViolation >(); + } +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexMetaDataRule.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexMetaDataRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexMetaDataRule.java new file mode 100644 index 0000000..a1f0552 --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexMetaDataRule.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import java.util.List; + +import com.adobe.ac.pmd.nodes.IAttribute; +import com.adobe.ac.pmd.nodes.IClass; +import com.adobe.ac.pmd.nodes.IFunction; +import com.adobe.ac.pmd.nodes.IMetaDataListHolder; + +/** + * @author xagnetti + */ +public abstract class AbstractFlexMetaDataRule extends AbstractAstFlexRule +{ + /* + * (non-Javadoc) + * @see + * com.adobe.ac.pmd.rules.core.AbstractAstFlexRule#findViolations(com.adobe + * .ac.pmd.nodes.IClass) + */ + @Override + protected final void findViolations( final IClass classNode ) + { + super.findViolations( classNode ); + + if ( classNode.getMetaDataCount() > 0 ) + { + findViolationsFromMetaDataList( classNode ); + findViolationsFromClassMetaData( classNode ); + } + } + + /* + * (non-Javadoc) + * @see + * com.adobe.ac.pmd.rules.core.AbstractAstFlexRule#findViolations(com.adobe + * .ac.pmd.nodes.IFunction) + */ + @Override + protected final void findViolations( final IFunction function ) + { + if ( function.getMetaDataCount() > 0 ) + { + findViolationsFromMetaDataList( function ); + findViolationsFromFunctionMetaData( function ); + } + } + + /** + * @param function + */ + protected void findViolationsFromAttributeMetaData( final IAttribute attribute ) + { + } + + /* + * (non-Javadoc) + * @see + * com.adobe.ac.pmd.rules.core.AbstractAstFlexRule#findViolationsFromAttributes + * (java.util.List) + */ + @Override + protected final void findViolationsFromAttributes( final List< IAttribute > variables ) + { + for ( final IAttribute attribute : variables ) + { + if ( attribute.getMetaDataCount() > 0 ) + { + findViolationsFromMetaDataList( attribute ); + findViolationsFromAttributeMetaData( attribute ); + } + } + } + + /** + * @param classNode + */ + protected void findViolationsFromClassMetaData( final IClass classNode ) + { + } + + /** + * @param function + */ + protected void findViolationsFromFunctionMetaData( final IFunction function ) + { + } + + /** + * @param holder + */ + protected void findViolationsFromMetaDataList( final IMetaDataListHolder holder ) + { + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRule.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRule.java new file mode 100644 index 0000000..2611ccf --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRule.java @@ -0,0 +1,354 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +import net.sourceforge.pmd.CommonAbstractRule; +import net.sourceforge.pmd.PropertyDescriptor; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.rules.regex.RegexHelper; + +import org.apache.commons.lang.StringUtils; + +import com.adobe.ac.pmd.IFlexViolation; +import com.adobe.ac.pmd.files.IFlexFile; +import com.adobe.ac.pmd.nodes.IPackage; +import com.adobe.ac.pmd.rules.core.thresholded.IThresholdedRule; + +/** + * Abstract FlexPMD rule. Extends this class if you want to find violations at a + * very low level. Otherwise extends AbstractAstFlexRule, or + * AbstractRegexpBasedRule. + * + * @author xagnetti + */ +public abstract class AbstractFlexRule extends CommonAbstractRule implements IFlexRule +{ + protected static final String MAXIMUM = "maximum"; + protected static final String MINIMUM = "minimum"; + private static final String AS3_COMMENT_TOKEN = "//"; + private static final Logger LOGGER = Logger.getLogger( AbstractFlexRule.class.getName() ); + private static final String MXML_COMMENT_TOKEN = "<!--"; + private IFlexFile currentFile; + private IPackage currentPackageNode; + private Set< String > excludes; + private Map< String, IFlexFile > filesInSourcePath; + + /** + * + */ + public AbstractFlexRule() + { + super(); + + setDefaultPriority(); + } + + /** + * not used in FlexPMD + */ + public final void apply( final List< ? > astCompilationUnits, + final RuleContext ctx ) + { + } + + /** + * @return Extracts the rulename from the qualified name of the underlying + * class + */ + public final String getRuleName() + { + final String qualifiedClassName = this.getClass().getName(); + final String className = StringUtils.substringAfter( qualifiedClassName, + "." ); + + return className.replace( "Rule", + "" ); + } + + /* + * (non-Javadoc) + * @see + * com.adobe.ac.pmd.rules.core.IFlexRule#processFile(com.adobe.ac.pmd.files + * .IFlexFile, com.adobe.ac.pmd.nodes.IPackage, java.util.Map) + */ + public final List< IFlexViolation > processFile( final IFlexFile file, + final IPackage packageNode, + final Map< String, IFlexFile > files ) + { + List< IFlexViolation > violations = new ArrayList< IFlexViolation >(); + + currentFile = file; + filesInSourcePath = files; + currentPackageNode = packageNode; + + if ( isConcernedByTheCurrentFile() + && !isFileExcluded( file ) ) + { + onRuleStart(); + violations = findViolationsInCurrentFile(); + } + + return violations; + } + + /* + * (non-Javadoc) + * @see com.adobe.ac.pmd.rules.core.IFlexRule#setExcludes(java.util.Set) + */ + public void setExcludes( final Set< String > excludesToBeSet ) + { + excludes = excludesToBeSet; + } + + /** + * @param violatedLine + * @return + */ + boolean isViolationIgnored( final String violatedLine ) + { + final boolean containsNoPmd = lineContainsNoPmd( violatedLine, + MXML_COMMENT_TOKEN ) + || lineContainsNoPmd( violatedLine, + AS3_COMMENT_TOKEN ); + + if ( !containsNoPmd ) + { + return false; + } + final String name = getRuleName().replaceAll( "Rule", + "" ); + final String ruleName = name.contains( "." ) ? StringUtils.substringAfterLast( name, + "." ) + : name; + final String strippedLine = computeStrippedLine( violatedLine ); + return strippedLineContainsNoPmdAndRuleName( MXML_COMMENT_TOKEN, + ruleName, + strippedLine ) + || strippedLineContainsNoPmdAndRuleName( AS3_COMMENT_TOKEN, + ruleName, + strippedLine ); + } + + /** + * @param violations + * @param position + * @return + */ + protected final IFlexViolation addViolation( final List< IFlexViolation > violations, + final ViolationPosition position ) + { + final IFlexViolation violation = new Violation( position, this, getCurrentFile() ); + final int beginLine = position.getBeginLine(); + + prettyPrintMessage( violation ); + + if ( beginLine == -1 + || beginLine == 0 ) + { + violations.add( violation ); + } + else if ( beginLine <= getCurrentFile().getLinesNb() ) + { + if ( isViolationIgnored( getCurrentFile().getLineAt( beginLine ) ) ) + { + LOGGER.info( getRuleName() + + " has been ignored in " + getCurrentFile().getFilename() + " (" + beginLine + ")" ); + } + else + { + violations.add( violation ); + } + } + + return violation; + } + + protected final IFlexViolation addViolation( final List< IFlexViolation > violations, + final ViolationPosition position, + final String... messageToReplace ) + { + final IFlexViolation violation = addViolation( violations, + position ); + + for ( int i = 0; i < messageToReplace.length; i++ ) + { + violation.replacePlaceholderInMessage( messageToReplace[ i ], + i ); + } + + return violation; + } + + /** + * @return + */ + protected abstract List< IFlexViolation > findViolationsInCurrentFile(); + + /** + * @return the current file under investigation + */ + protected IFlexFile getCurrentFile() + { + return currentFile; + } + + /** + * @return + */ + protected final IPackage getCurrentPackageNode() + { + return currentPackageNode; + } + + /** + * @return + */ + protected abstract ViolationPriority getDefaultPriority(); + + /** + * @return + */ + protected final Map< String, IFlexFile > getFilesInSourcePath() + { + return filesInSourcePath; + } + + /** + * @param rule + * @return + */ + protected final Map< String, PropertyDescriptor > getThresholdedRuleProperties( final IThresholdedRule rule ) + { + final Map< String, PropertyDescriptor > properties = new LinkedHashMap< String, PropertyDescriptor >(); + + properties.put( rule.getThresholdName(), + new IntegerProperty( rule.getThresholdName(), + "", + rule.getDefaultThreshold(), + properties.size() ) ); + + return properties; + } + + /** + * @return is this rule concerned by the current file + */ + protected abstract boolean isConcernedByTheCurrentFile(); + + /** + * Called when the rule is started on the current file + */ + protected void onRuleStart() + { + } + + private String computeStrippedLine( final String violatedLine ) + { + final String comment_token = getCurrentFile().isMxml() ? MXML_COMMENT_TOKEN + : AS3_COMMENT_TOKEN; + String strippedLine = violatedLine; + + if ( violatedLine.indexOf( comment_token + + " N" ) > 0 ) + { + strippedLine = StringUtils.strip( violatedLine.substring( violatedLine.indexOf( comment_token + + " N" ) ) ); + } + else if ( violatedLine.indexOf( comment_token + + "N" ) > 0 ) + { + strippedLine = StringUtils.strip( violatedLine.substring( violatedLine.indexOf( comment_token + + "N" ) ) ); + } + return strippedLine; + } + + private boolean isFileExcluded( final IFlexFile file ) + { + if ( excludes != null ) + { + for ( final String exclusion : excludes ) + { + final Pattern pattern = Pattern.compile( exclusion ); + + if ( RegexHelper.isMatch( pattern, + file.getFilePath() ) ) + { + return true; + } + } + } + return false; + } + + private boolean lineContainsNoPmd( final String violatedLine, + final String comment_token ) + { + return violatedLine.contains( comment_token + + " No PMD" ) + || violatedLine.contains( comment_token + + " NO PMD" ) || violatedLine.contains( comment_token + + " NOPMD" ) || violatedLine.contains( comment_token + + "NOPMD" ); + } + + private void prettyPrintMessage( final IFlexViolation violation ) + { + final int nbOfBraces = violation.getRuleMessage().split( "\\{" ).length - 1; + + if ( this instanceof IThresholdedRule ) + { + final IThresholdedRule thresholdeRule = ( IThresholdedRule ) this; + + violation.replacePlaceholderInMessage( String.valueOf( thresholdeRule.getThreshold() ), + nbOfBraces - 2 ); + violation.replacePlaceholderInMessage( String.valueOf( thresholdeRule.getActualValueForTheCurrentViolation() ), + nbOfBraces - 1 ); + } + if ( getDescription() != null ) + { + violation.appendToMessage( ". " ); + violation.appendToMessage( getDescription() ); + } + } + + private void setDefaultPriority() + { + setPriority( Integer.valueOf( getDefaultPriority().toString() ) ); + } + + private boolean strippedLineContainsNoPmdAndRuleName( final String comment_token, + final String ruleName, + final String strippedLine ) + { + return strippedLine.endsWith( comment_token + + " No PMD" ) + || strippedLine.endsWith( comment_token + + " NO PMD" ) || strippedLine.endsWith( comment_token + + " NOPMD" ) || strippedLine.endsWith( comment_token + + "NOPMD" ) || strippedLine.contains( ruleName ); + } +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRuleTest.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRuleTest.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRuleTest.java new file mode 100644 index 0000000..ac44b0c --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRuleTest.java @@ -0,0 +1,264 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import com.adobe.ac.pmd.FlexPmdTestBase; +import com.adobe.ac.pmd.IFlexViolation; +import com.adobe.ac.pmd.files.IFlexFile; +import com.adobe.ac.pmd.parser.exceptions.TokenException; + +public abstract class AbstractFlexRuleTest extends FlexPmdTestBase +{ + final static class AssertPosition + { + public static AssertPosition create( final String message, + final int expectedLine, + final int actualLine ) + { + return new AssertPosition( message, expectedLine, actualLine ); + } + + public int actualLine; + public int expectedLine; + public String message; + + private AssertPosition( final String messageToBeSet, + final int expectedLineToBeSet, + final int actualLineToBeSet ) + { + super(); + message = messageToBeSet; + expectedLine = expectedLineToBeSet; + actualLine = actualLineToBeSet; + } + } + + protected final static class ExpectedViolation + { + protected String file; + protected ViolationPosition[] positions; + + public ExpectedViolation( final String fileToBeSet, + final ViolationPosition[] positionsToBeSet ) + { + super(); + file = fileToBeSet; + positions = positionsToBeSet; + } + } + + protected static StringBuffer buildFailuresMessage( final List< AssertPosition > failures ) + { + final StringBuffer message = new StringBuffer( 42 ); + + for ( final AssertPosition assertPosition : failures ) + { + message.append( assertPosition.message + + ": expected <" + assertPosition.expectedLine + "> but actually <" + + assertPosition.actualLine + ">\n" ); + } + return message; + } + + protected static List< AssertPosition > buildFailureViolations( final String resourcePath, + final ViolationPosition[] expectedPositions, + final List< IFlexViolation > violations ) + { + List< AssertPosition > failures; + failures = new ArrayList< AssertPosition >(); + + for ( int i = 0; i < expectedPositions.length; i++ ) + { + final IFlexViolation violation = violations.get( i ); + final ViolationPosition expectedPosition = expectedPositions[ i ]; + + if ( expectedPosition.getBeginLine() != violation.getBeginLine() ) + { + failures.add( AssertPosition.create( BEGIN_LINE_NOT_CORRECT + + " at " + i + "th violation on " + resourcePath, + expectedPosition.getBeginLine(), + violation.getBeginLine() ) ); + } + if ( expectedPosition.getEndLine() != violation.getEndLine() ) + { + failures.add( AssertPosition.create( END_LINE_NOT_CORRECT + + " at " + i + "th violation on " + resourcePath, + expectedPosition.getEndLine(), + violation.getEndLine() ) ); + } + } + return failures; + } + + protected static StringBuffer buildMessageName( final Map< String, List< IFlexViolation >> violatedFiles ) + { + final StringBuffer buffer = new StringBuffer( 100 ); + + for ( final String violatedFileName : violatedFiles.keySet() ) + { + final List< IFlexViolation > violations = violatedFiles.get( violatedFileName ); + + buffer.append( violatedFileName + + " should not contain any violations " + " (" + violations.size() + " found" ); + + if ( violations.size() == 1 ) + { + buffer.append( " at " + + violations.get( 0 ).getBeginLine() + ":" + violations.get( 0 ).getEndLine() ); + } + buffer.append( ")\n" ); + } + return buffer; + } + + /** + * Test case which contains non-concerned files by the given rule + * + * @throws TokenException + * @throws IOException + */ + @Test + public final void testProcessNonViolatingFiles() throws IOException, + TokenException + { + final Map< String, List< IFlexViolation >> violatedFiles = extractActualViolatedFiles(); + final StringBuffer buffer = buildMessageName( violatedFiles ); + + if ( !violatedFiles.isEmpty() ) + { + fail( buffer.toString() ); + } + } + + /** + * Test case which contains violating files + */ + @Test + public final void testProcessViolatingFiles() + { + final Map< String, ViolationPosition[] > expectedPositions = computeExpectedViolations( getExpectedViolatingFiles() ); + + for ( final String fileName : expectedPositions.keySet() ) + { + assertViolations( fileName, + expectedPositions.get( fileName ) ); + } + } + + protected abstract ExpectedViolation[] getExpectedViolatingFiles(); + + protected List< String > getIgnoreFiles() + { + return new ArrayList< String >(); + } + + protected abstract AbstractFlexRule getRule(); + + protected List< IFlexViolation > processFile( final String resourcePath ) throws IOException, + TokenException + { + if ( !getIgnoreFiles().contains( resourcePath ) ) + { + return getRule().processFile( getTestFiles().get( resourcePath ), + null, + getTestFiles() ); + } + return new ArrayList< IFlexViolation >(); + } + + private void assertViolations( final String resourcePath, + final ViolationPosition[] expectedPositions ) + { + try + { + final List< IFlexViolation > violations = processFile( resourcePath ); + + assertEquals( VIOLATIONS_NUMBER_NOT_CORRECT + + " for " + resourcePath, + expectedPositions.length, + violations.size() ); + + if ( expectedPositions.length != 0 ) + { + printFailures( buildFailureViolations( resourcePath, + expectedPositions, + violations ) ); + } + } + catch ( final IOException e ) + { + fail( e.getMessage() ); + } + catch ( final TokenException e ) + { + fail( e.getMessage() ); + } + } + + private Map< String, ViolationPosition[] > computeExpectedViolations( final ExpectedViolation[] expectedViolatingFiles ) + { + final Map< String, ViolationPosition[] > expectedViolations = new LinkedHashMap< String, ViolationPosition[] >(); + + for ( final ExpectedViolation expectedViolatingFile : expectedViolatingFiles ) + { + expectedViolations.put( expectedViolatingFile.file, + expectedViolatingFile.positions ); + } + return expectedViolations; + } + + private Map< String, List< IFlexViolation >> extractActualViolatedFiles() throws IOException, + TokenException + { + final Map< String, List< IFlexViolation > > violatedFiles = new LinkedHashMap< String, List< IFlexViolation > >(); + final Map< String, ViolationPosition[] > expectedPositions = computeExpectedViolations( getExpectedViolatingFiles() ); + + for ( final Map.Entry< String, IFlexFile > fileNameEntry : getTestFiles().entrySet() ) + { + if ( !expectedPositions.containsKey( fileNameEntry.getKey() ) ) + { + final List< IFlexViolation > violations = processFile( fileNameEntry.getKey() ); + + if ( !violations.isEmpty() ) + { + violatedFiles.put( fileNameEntry.getKey(), + violations ); + } + } + } + return violatedFiles; + } + + private void printFailures( final List< AssertPosition > failures ) + { + if ( !failures.isEmpty() ) + { + fail( buildFailuresMessage( failures ).toString() ); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractForbiddenImportRule.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractForbiddenImportRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractForbiddenImportRule.java new file mode 100644 index 0000000..5c54876 --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractForbiddenImportRule.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import com.adobe.ac.pmd.nodes.IPackage; +import com.adobe.ac.pmd.parser.IParserNode; + +/** + * @author xagnetti + */ +public abstract class AbstractForbiddenImportRule extends AbstractAstFlexRule +{ + + /** + * + */ + public AbstractForbiddenImportRule() + { + super(); + } + + /* + * (non-Javadoc) + * @see + * com.adobe.ac.pmd.rules.core.AbstractAstFlexRule#findViolations(com.adobe + * .ac.pmd.nodes.IPackage) + */ + @Override + protected final void findViolations( final IPackage packageNode ) + { + for ( final IParserNode importNode : packageNode.getImports() ) + { + if ( importNode.getStringValue().contains( getForbiddenImport() ) ) + { + addViolation( importNode ); + } + } + } + + /** + * @return + */ + protected abstract String getForbiddenImport(); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractPrimaryAstRule.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractPrimaryAstRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractPrimaryAstRule.java new file mode 100644 index 0000000..7479a2a --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractPrimaryAstRule.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import java.util.List; + +import com.adobe.ac.pmd.nodes.IFunction; +import com.adobe.ac.pmd.parser.IParserNode; + +/** + * Abstract rule which find a primary (or a couple of primaries) in a body + * function. + * + * @author xagnetti + */ +public abstract class AbstractPrimaryAstRule extends AbstractAstFlexRule +{ + /** + * @param statement + * @param function + */ + protected abstract void addViolation( IParserNode statement, + IFunction function ); + + /* + * (non-Javadoc) + * @see + * com.adobe.ac.pmd.rules.core.AbstractAstFlexRule#findViolations(com.adobe + * .ac.pmd.nodes.IFunction) + */ + @Override + protected final void findViolations( final IFunction function ) + { + final List< IParserNode > firstStatements = function.findPrimaryStatementsInBody( getFirstPrimaryToFind() ); + if ( !firstStatements.isEmpty() ) + { + for ( final IParserNode firstStatement : firstStatements ) + { + if ( getSecondPrimaryToFind() == null ) + { + addViolation( firstStatement, + function ); + } + else + { + final List< IParserNode > secondStatements = function.findPrimaryStatementsInBody( getSecondPrimaryToFind() ); + if ( !secondStatements.isEmpty() ) + { + for ( final IParserNode secondStatement : secondStatements ) + { + addViolation( secondStatement, + function ); + } + } + } + } + } + } + + /** + * @return + */ + protected abstract String getFirstPrimaryToFind(); + + /** + * @return + */ + protected String getSecondPrimaryToFind() + { + return null; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegExpBasedRuleTest.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegExpBasedRuleTest.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegExpBasedRuleTest.java new file mode 100644 index 0000000..527e1cf --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegExpBasedRuleTest.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import junit.framework.Assert; + +import org.junit.Test; + +public abstract class AbstractRegExpBasedRuleTest extends AbstractFlexRuleTest +{ + @Test + public void testDoesCurrentLineMacthCorrectLine() + { + final AbstractRegexpBasedRule rule = getRegexpBasedRule(); + + if ( getMatchableLines().length == 0 ) + { + Assert.fail( "the getMatchableLines() is empty" ); + } + for ( int i = 0; i < getMatchableLines().length; i++ ) + { + final String correctLine = getMatchableLines()[ i ]; + + assertTrue( "This line (\"" + + correctLine + "\") should be matched", + rule.doesCurrentLineMacthes( correctLine ) ); + } + } + + @Test + public void testDoesCurrentLineMacthIncorrectLine() + { + final AbstractRegexpBasedRule rule = getRegexpBasedRule(); + + if ( getUnmatchableLines().length == 0 ) + { + Assert.fail( "the getUnmatchableLines() is empty" ); + } + for ( int i = 0; i < getUnmatchableLines().length; i++ ) + { + final String incorrectLine = getUnmatchableLines()[ i ]; + + assertFalse( "This line (\"" + + incorrectLine + "\") should not be matched", + rule.doesCurrentLineMacthes( incorrectLine ) ); + } + } + + protected abstract String[] getMatchableLines(); + + protected abstract AbstractRegexpBasedRule getRegexpBasedRule(); + + @Override + protected AbstractFlexRule getRule() + { + return getRegexpBasedRule(); + } + + protected abstract String[] getUnmatchableLines(); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegexpBasedRule.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegexpBasedRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegexpBasedRule.java new file mode 100644 index 0000000..cfc71de --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegexpBasedRule.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.adobe.ac.pmd.IFlexViolation; + +/** + * @author xagnetti + */ +public abstract class AbstractRegexpBasedRule extends AbstractFlexRule +{ + private Pattern pattern; + + /** + * + */ + public AbstractRegexpBasedRule() + { + super(); + compilePattern(); + } + + /** + * + */ + public final void compilePattern() + { + pattern = Pattern.compile( getRegexp() ); + } + + /* + * (non-Javadoc) + * @see + * com.adobe.ac.pmd.rules.core.AbstractFlexRule#findViolationsInCurrentFile() + */ + @Override + public final List< IFlexViolation > findViolationsInCurrentFile() + { + final List< IFlexViolation > violations = new ArrayList< IFlexViolation >(); + + if ( "".compareTo( getRegexp() ) != 0 ) + { + for ( int i = 1; i <= getCurrentFile().getLinesNb(); i++ ) + { + final String line = getCurrentFile().getLineAt( i ); + + if ( isCurrentLineConcerned( line ) + && doesCurrentLineMacthes( line ) && isViolationDetectedOnThisMatchingLine( line ) + && !line.contains( "/*" ) && !line.contains( "//" ) ) + { + addViolation( violations, + ViolationPosition.create( i, + i, + 0, + line.length() ) ); + } + } + } + return violations; + } + + /** + * @param line + * @return + */ + final boolean doesCurrentLineMacthes( final String line ) + { + return getMatcher( line ).matches(); + } + + /** + * @param line + * @return + */ + protected final Matcher getMatcher( final String line ) + { + final Matcher matcher = pattern.matcher( line ); + + return matcher; + } + + /** + * @return + */ + protected abstract String getRegexp(); + + protected boolean isCurrentLineConcerned( final String line ) + { + return true; + } + + /** + * @param line + * @return + */ + protected abstract boolean isViolationDetectedOnThisMatchingLine( final String line ); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractXpathRelatedRule.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractXpathRelatedRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractXpathRelatedRule.java new file mode 100644 index 0000000..72dadfb --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractXpathRelatedRule.java @@ -0,0 +1,244 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import com.adobe.ac.pmd.IFlexViolation; +import com.adobe.ac.utils.StackTraceUtils; + +/** + * @author xagnetti + */ +public abstract class AbstractXpathRelatedRule extends AbstractFlexRule +{ + /** + * @author xagnetti + */ + public class NamespaceContextMap implements NamespaceContext + { + private final Map< String, String > prefixMap; + + /** + * Constructor that takes a map of XML prefix-namespaceURI values. A + * defensive copy is made of the map. An IllegalArgumentException will be + * thrown if the map attempts to remap the standard prefixes defined in + * the NamespaceContext contract. + * + * @param prefixMappings a map of prefix:namespaceURI values + */ + public NamespaceContextMap( final Map< String, String > prefixMappings ) + { + prefixMap = createPrefixMap( prefixMappings ); + } + + /** + * Convenience constructor. + * + * @param mappingPairs pairs of prefix-namespaceURI values + */ + public NamespaceContextMap( final String... mappingPairs ) + { + this( toMap( mappingPairs ) ); + } + + /* + * (non-Javadoc) + * @see + * javax.xml.namespace.NamespaceContext#getNamespaceURI(java.lang.String) + */ + public String getNamespaceURI( final String prefix ) + { + prefixMap.get( prefix ); + return prefixMap.get( prefix ); + } + + /* + * (non-Javadoc) + * @see javax.xml.namespace.NamespaceContext#getPrefix(java.lang.String) + */ + public String getPrefix( final String namespaceURI ) + { + return null; + } + + /* + * (non-Javadoc) + * @see javax.xml.namespace.NamespaceContext#getPrefixes(java.lang.String) + */ + public Iterator< String > getPrefixes( final String namespaceURI ) + { + return null; + } + + private void addConstant( final Map< String, String > map, + final String prefix, + final String nsURI ) + { + map.put( prefix, + nsURI ); + } + + private Map< String, String > createPrefixMap( final Map< String, String > prefixMappings ) + { + final Map< String, String > map = new LinkedHashMap< String, String >( prefixMappings ); + addConstant( map, + XMLConstants.XML_NS_PREFIX, + XMLConstants.XML_NS_URI ); + addConstant( map, + XMLConstants.XMLNS_ATTRIBUTE, + XMLConstants.XMLNS_ATTRIBUTE_NS_URI ); + return Collections.unmodifiableMap( map ); + } + + } + + protected static final Logger LOGGER = Logger.getLogger( AbstractXpathRelatedRule.class.getName() ); + + private static Map< String, String > toMap( final String... mappingPairs ) + { + final Map< String, String > prefixMappings = new LinkedHashMap< String, String >( mappingPairs.length / 2 ); + for ( int i = 0; i < mappingPairs.length; i++ ) + { + prefixMappings.put( mappingPairs[ i ], + mappingPairs[ ++i ] ); + } + return prefixMappings; + } + + /** + * @param doc + * @param xPath + * @return + * @throws XPathExpressionException + */ + protected abstract Object evaluate( final Document doc, + final XPath xPath ) throws XPathExpressionException; + + /* + * (non-Javadoc) + * @see + * com.adobe.ac.pmd.rules.core.AbstractFlexRule#findViolationsInCurrentFile() + */ + @Override + protected List< IFlexViolation > findViolationsInCurrentFile() + { + final ArrayList< IFlexViolation > violations = new ArrayList< IFlexViolation >(); + + try + { + final Document doc = buildDocument(); + final XPath xPath = buildXPath(); + + onEvaluated( violations, + doc, + xPath ); + } + catch ( final XPathExpressionException e ) + { + LOGGER.warning( StackTraceUtils.print( getCurrentFile().getFilename(), + e ) ); + } + catch ( final FileNotFoundException e ) + { + LOGGER.warning( StackTraceUtils.print( getCurrentFile().getFilename(), + e ) ); + } + catch ( final ParserConfigurationException e ) + { + LOGGER.warning( StackTraceUtils.print( getCurrentFile().getFilename(), + e ) ); + } + catch ( final SAXException e ) + { + LOGGER.warning( StackTraceUtils.print( getCurrentFile().getFilename(), + e ) ); + } + catch ( final IOException e ) + { + LOGGER.warning( StackTraceUtils.print( getCurrentFile().getFilename(), + e ) ); + } + + return violations; + } + + /** + * @return + */ + protected abstract String getXPathExpression(); + + /* + * (non-Javadoc) + * @see + * com.adobe.ac.pmd.rules.core.AbstractFlexRule#isConcernedByTheCurrentFile() + */ + @Override + protected boolean isConcernedByTheCurrentFile() + { + return getCurrentFile().isMxml(); + } + + /** + * @param violations + * @param doc + * @param xPath + * @throws XPathExpressionException + */ + protected abstract void onEvaluated( final List< IFlexViolation > violations, + final Document doc, + final XPath xPath ) throws XPathExpressionException; + + private Document buildDocument() throws ParserConfigurationException, + SAXException, + IOException + { + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware( true ); + final DocumentBuilder builder = factory.newDocumentBuilder(); + return builder.parse( getCurrentFile().getFilePath() ); + } + + private XPath buildXPath() + { + final XPathFactory xPathFactory = XPathFactory.newInstance(); + final XPath xPath = xPathFactory.newXPath(); + xPath.setNamespaceContext( new NamespaceContextMap( "mx", "http://www.adobe.com/2006/mxml" ) ); + return xPath; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexAstRule.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexAstRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexAstRule.java new file mode 100644 index 0000000..7cfcee4 --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexAstRule.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +/** + * @author xagnetti + */ +public interface IFlexAstRule extends IFlexRule +{ + /** + * @return true if the current file is concerned + */ + boolean isConcernedByTheCurrentFile(); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexRule.java ---------------------------------------------------------------------- diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexRule.java new file mode 100644 index 0000000..3eb94e4 --- /dev/null +++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexRule.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.adobe.ac.pmd.rules.core; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import net.sourceforge.pmd.Rule; + +import com.adobe.ac.pmd.IFlexViolation; +import com.adobe.ac.pmd.files.IFlexFile; +import com.adobe.ac.pmd.nodes.IPackage; + +/** + * @author xagnetti + */ +public interface IFlexRule extends Rule +{ + /** + * @return ruleName + */ + String getRuleName(); + + /** + * @param file + * @param rootNode + * @param files + * @return + */ + List< IFlexViolation > processFile( final IFlexFile file, + final IPackage rootNode, + final Map< String, IFlexFile > files ); + + /** + * @param excludes + */ + void setExcludes( final Set< String > excludes ); +} \ No newline at end of file