flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aha...@apache.org
Subject [23/46] FlexPMD Donation from Adobe Systems Inc
Date Fri, 25 Apr 2014 06:18:22 GMT
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/MetaDataNode.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/MetaDataNode.java b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/MetaDataNode.java
new file mode 100644
index 0000000..edb9777
--- /dev/null
+++ b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/MetaDataNode.java
@@ -0,0 +1,139 @@
+/*
+ * 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.nodes.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.adobe.ac.pmd.nodes.IMetaData;
+import com.adobe.ac.pmd.parser.IParserNode;
+
+/**
+ * @author xagnetti
+ */
+class MetaDataNode extends AbstractNode implements IMetaData
+{
+   private List< String >          attributeNames;
+   private String                  name;
+   private String                  parameter;
+   private Map< String, String[] > parameters;
+
+   /**
+    * @param node
+    */
+   protected MetaDataNode( final IParserNode node )
+   {
+      super( node );
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.impl.AbstractNode#compute()
+    */
+   @Override
+   public MetaDataNode compute()
+   {
+      final String stringValue = getInternalNode().getStringValue();
+
+      name = stringValue.indexOf( " ( " ) > -1 ? stringValue.substring( 0,
+                                                                        stringValue.indexOf( " ( " ) )
+                                              : stringValue;
+      parameter = stringValue.indexOf( "( " ) > -1 ? stringValue.substring( stringValue.indexOf( "( " ) + 2,
+                                                                            stringValue.lastIndexOf( " )" ) )
+                                                  : "";
+
+      computeAttributeNames();
+      return this;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IMetaData#getAttributeNames()
+    */
+   public List< String > getAttributeNames()
+   {
+      return attributeNames;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IMetaData#getDefaultValue()
+    */
+   public String getDefaultValue()
+   {
+      return parameter;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.INamable#getName()
+    */
+   public String getName()
+   {
+      return name;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IMetaData#getProperty(java.lang.String)
+    */
+   public String[] getProperty( final String property )
+   {
+      return parameters.containsKey( property ) ? parameters.get( property )
+                                               : new String[]
+                                               {};
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IMetaData#getPropertyAsList(java.lang.String)
+    */
+   public List< String > getPropertyAsList( final String property )
+   {
+      return Arrays.asList( getProperty( property ) );
+   }
+
+   private void computeAttributeNames()
+   {
+      attributeNames = new ArrayList< String >();
+      parameters = new LinkedHashMap< String, String[] >();
+
+      final String[] pairs = getPairs();
+
+      for ( final String pair : pairs )
+      {
+         final String[] pairSplit = pair.split( "=" );
+
+         if ( pairSplit.length == 2 )
+         {
+            attributeNames.add( pairSplit[ 0 ].trim() );
+            parameters.put( pairSplit[ 0 ].trim(),
+                            pairSplit[ 1 ].trim().replaceAll( "\'",
+                                                              "" ).replaceAll( "\"",
+                                                                               "" ).split( "," ) );
+         }
+      }
+   }
+
+   private String[] getPairs()
+   {
+      return parameter.split( "," );
+   }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/NodeFactory.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/NodeFactory.java b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/NodeFactory.java
new file mode 100644
index 0000000..1a9aac8
--- /dev/null
+++ b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/NodeFactory.java
@@ -0,0 +1,49 @@
+/*
+ * 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.nodes.impl;
+
+import com.adobe.ac.pmd.nodes.IMetaData;
+import com.adobe.ac.pmd.nodes.IPackage;
+import com.adobe.ac.pmd.parser.IParserNode;
+
+/**
+ * @author xagnetti
+ */
+public final class NodeFactory
+{
+   /**
+    * @param metadataNode
+    * @return
+    */
+   public static IMetaData createMetaData( final IParserNode metadataNode )
+   {
+      return new MetaDataNode( metadataNode ).compute();
+   }
+
+   /**
+    * @param packageNode
+    * @return
+    */
+   public static IPackage createPackage( final IParserNode packageNode )
+   {
+      return new PackageNode( packageNode ).compute();
+   }
+
+   private NodeFactory()
+   {
+   }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/PackageNode.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/PackageNode.java b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/PackageNode.java
new file mode 100644
index 0000000..f8bd8b5
--- /dev/null
+++ b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/PackageNode.java
@@ -0,0 +1,167 @@
+/*
+ * 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.nodes.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.adobe.ac.pmd.nodes.IClass;
+import com.adobe.ac.pmd.nodes.IFunction;
+import com.adobe.ac.pmd.nodes.IPackage;
+import com.adobe.ac.pmd.parser.IParserNode;
+import com.adobe.ac.pmd.parser.NodeKind;
+
+/**
+ * @author xagnetti
+ */
+class PackageNode extends AbstractNode implements IPackage
+{
+   private IClass                    classNode;
+   private final List< IFunction >   functions;
+   private final List< IParserNode > imports;
+   private String                    name;
+
+   /**
+    * @param node
+    */
+   protected PackageNode( final IParserNode node )
+   {
+      super( node );
+
+      imports = new ArrayList< IParserNode >();
+      functions = new ArrayList< IFunction >();
+      classNode = null;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.impl.AbstractNode#compute()
+    */
+   @Override
+   public PackageNode compute()
+   {
+      final IParserNode classWrapperNode = getClassNodeFromCompilationUnitNode( getInternalNode(),
+                                                                                3 );
+      final IParserNode firstChild = getInternalNode().getChild( 0 );
+
+      if ( firstChild.numChildren() > 0
+            && firstChild.getChild( 0 ).getStringValue() != null )
+      {
+         name = firstChild.getChild( 0 ).getStringValue();
+      }
+      else
+      {
+         name = "";
+      }
+      if ( classWrapperNode != null )
+      {
+         classNode = new ClassNode( classWrapperNode ).compute();
+      }
+
+      if ( firstChild.numChildren() > 1
+            && firstChild.getChild( 1 ).numChildren() != 0 )
+      {
+         final List< IParserNode > children = firstChild.getChild( 1 ).getChildren();
+
+         for ( final IParserNode node : children )
+         {
+            if ( node.is( NodeKind.IMPORT ) )
+            {
+               imports.add( node );
+            }
+         }
+      }
+      return this;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IPackage#getClassNode()
+    */
+   public IClass getClassNode()
+   {
+      return classNode;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IPackage#getFullyQualifiedClassName()
+    */
+   public String getFullyQualifiedClassName()
+   {
+      if ( !"".equals( name ) )
+      {
+         return name
+               + "." + classNode.getName();
+      }
+      return classNode == null ? ""
+                              : classNode.getName();
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IPackage#getFunctions()
+    */
+   public List< IFunction > getFunctions()
+   {
+      return functions;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IPackage#getImports()
+    */
+   public List< IParserNode > getImports()
+   {
+      return imports;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.INamable#getName()
+    */
+   public String getName()
+   {
+      return name;
+   }
+
+   private IParserNode getClassNodeFromCompilationUnitNode( final IParserNode node,
+                                                            final int depth )
+   {
+      if ( depth == 0
+            || node.numChildren() == 0 )
+      {
+         return null;
+      }
+      for ( final IParserNode child : node.getChildren() )
+      {
+         if ( child.is( NodeKind.CLASS )
+               || child.is( NodeKind.INTERFACE ) )
+         {
+            return child;
+         }
+         final IParserNode localClassNode = getClassNodeFromCompilationUnitNode( child,
+                                                                                 depth - 1 );
+
+         if ( localClassNode != null )
+         {
+            return localClassNode;
+         }
+      }
+      return null;
+   }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/VariableNode.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/VariableNode.java b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/VariableNode.java
new file mode 100644
index 0000000..3f64380
--- /dev/null
+++ b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/impl/VariableNode.java
@@ -0,0 +1,224 @@
+/*
+ * 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.nodes.impl;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import com.adobe.ac.pmd.nodes.IFieldInitialization;
+import com.adobe.ac.pmd.nodes.IIdentifierNode;
+import com.adobe.ac.pmd.nodes.IMetaData;
+import com.adobe.ac.pmd.nodes.IModifiersHolder;
+import com.adobe.ac.pmd.nodes.IVariable;
+import com.adobe.ac.pmd.nodes.MetaData;
+import com.adobe.ac.pmd.nodes.Modifier;
+import com.adobe.ac.pmd.parser.IParserNode;
+import com.adobe.ac.pmd.parser.NodeKind;
+
+/**
+ * Node representing a variable (var i : int = 0) It contains the variable name,
+ * its type name, the list of modifiers, the list of metadata, and the
+ * initialization expression (if any).
+ * 
+ * @author xagnetti
+ */
+class VariableNode extends AbstractNode implements IVariable, IModifiersHolder
+{
+   private IFieldInitialization                     initializationExpression;
+   private final Map< MetaData, List< IMetaData > > metaDataList;
+   private final Set< Modifier >                    modifiers;
+   private IdentifierNode                           name;
+   private IdentifierNode                           type;
+
+   /**
+    * @param rootNode
+    */
+   protected VariableNode( final IParserNode rootNode )
+   {
+      super( rootNode );
+
+      metaDataList = new LinkedHashMap< MetaData, List< IMetaData > >();
+      modifiers = new HashSet< Modifier >();
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.nodes.IMetaDataListHolder#add(com.adobe.ac.pmd.nodes.
+    * IMetaData)
+    */
+   public void add( final IMetaData metaData )
+   {
+      final MetaData metaDataImpl = MetaData.create( metaData.getName() );
+      if ( !metaDataList.containsKey( metaDataImpl ) )
+      {
+         metaDataList.put( metaDataImpl,
+                           new ArrayList< IMetaData >() );
+      }
+      metaDataList.get( metaDataImpl ).add( metaData );
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.nodes.IModifiersHolder#add(com.adobe.ac.pmd.nodes.Modifier
+    * )
+    */
+   public void add( final Modifier modifier )
+   {
+      modifiers.add( modifier );
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.impl.AbstractNode#compute()
+    */
+   @Override
+   public VariableNode compute()
+   {
+      if ( getInternalNode().is( NodeKind.NAME_TYPE_INIT ) )
+      {
+         computeNameTypeInit( getInternalNode() );
+      }
+      else
+      {
+         if ( getInternalNode().numChildren() != 0 )
+         {
+            for ( final IParserNode child : getInternalNode().getChildren() )
+            {
+               if ( child.is( NodeKind.NAME_TYPE_INIT ) )
+               {
+                  computeNameTypeInit( child );
+               }
+               else if ( child.is( NodeKind.META_LIST ) )
+               {
+                  computeMetaDataList( this,
+                                       child );
+               }
+            }
+         }
+      }
+      return this;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IMetaDataListHolder#getAllMetaData()
+    */
+   public List< IMetaData > getAllMetaData()
+   {
+      final List< IMetaData > list = new ArrayList< IMetaData >();
+
+      for ( final Entry< MetaData, List< IMetaData > > entry : metaDataList.entrySet() )
+      {
+         list.addAll( entry.getValue() );
+      }
+
+      return list;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IVariable#getInitializationExpression()
+    */
+   public IFieldInitialization getInitializationExpression()
+   {
+      return initializationExpression;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.nodes.IMetaDataListHolder#getMetaData(com.adobe.ac.pmd
+    * .nodes.MetaData)
+    */
+   public List< IMetaData > getMetaData( final MetaData metaDataName )
+   {
+      return metaDataList.get( metaDataName );
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IMetaDataListHolder#getMetaDataCount()
+    */
+   public int getMetaDataCount()
+   {
+      return metaDataList.size();
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.INamable#getName()
+    */
+   public String getName()
+   {
+      return name == null ? ""
+                         : name.toString();
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.nodes.IVariable#getType()
+    */
+   public IIdentifierNode getType()
+   {
+      return type;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.nodes.IModifiersHolder#is(com.adobe.ac.pmd.nodes.Modifier
+    * )
+    */
+   public boolean is( final Modifier modifier ) // NOPMD
+   {
+      return modifiers.contains( modifier );
+   }
+
+   private void computeNameTypeInit( final IParserNode nameTypeInit )
+   {
+      if ( nameTypeInit.numChildren() != 0 )
+      {
+         for ( final IParserNode child : nameTypeInit.getChildren() )
+         {
+            if ( child.is( NodeKind.NAME ) )
+            {
+               name = IdentifierNode.create( child );
+            }
+            else if ( child.is( NodeKind.TYPE ) )
+            {
+               type = IdentifierNode.create( child );
+            }
+            else if ( child.is( NodeKind.INIT ) )
+            {
+               initializationExpression = FieldInitializationNode.create( child );
+            }
+            else
+            {
+               LOGGER.warning( "unknown node type "
+                     + child.toString() );
+            }
+         }
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/utils/AsDocUtils.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/utils/AsDocUtils.java b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/utils/AsDocUtils.java
new file mode 100644
index 0000000..c363ca5
--- /dev/null
+++ b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/utils/AsDocUtils.java
@@ -0,0 +1,60 @@
+/*
+ * 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.nodes.utils;
+
+import com.adobe.ac.pmd.nodes.asdoc.impl.ClassAsDocNode;
+import com.adobe.ac.pmd.nodes.asdoc.impl.FunctionAsDocNode;
+import com.adobe.ac.pmd.nodes.asdoc.impl.ParameterAsDocNode;
+
+/**
+ * @author xagnetti
+ */
+public final class AsDocUtils
+{
+   /**
+    * @param doc
+    * @return
+    */
+   public static ClassAsDocNode computeClassDoc( final String doc )
+   {
+      return new ClassAsDocNode( doc );
+   }
+
+   /**
+    * @param doc
+    * @return
+    */
+   public static FunctionAsDocNode computeFunctionDoc( final String doc )
+   {
+      return new FunctionAsDocNode( doc );
+   }
+
+   /**
+    * @param nameToBeSet
+    * @param descriptionToBeSet
+    * @return
+    */
+   public static ParameterAsDocNode computeParameterDoc( final String nameToBeSet,
+                                                         final String descriptionToBeSet )
+   {
+      return new ParameterAsDocNode( nameToBeSet, descriptionToBeSet );
+   }
+
+   private AsDocUtils()
+   {
+   }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/utils/FunctionUtils.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/utils/FunctionUtils.java b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/utils/FunctionUtils.java
new file mode 100644
index 0000000..cc8d041
--- /dev/null
+++ b/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/nodes/utils/FunctionUtils.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.nodes.utils;
+
+import com.adobe.ac.ncss.utils.FileUtils;
+import com.adobe.ac.pmd.files.IFlexFile;
+import com.adobe.ac.pmd.parser.IParserNode;
+
+/**
+ * @author xagnetti
+ */
+public final class FunctionUtils
+{
+   /**
+    * @param currentFile
+    * @param block
+    * @return
+    */
+   public static int computeFunctionLength( final IFlexFile currentFile,
+                                            final IParserNode block )
+   {
+      int lineNb = 1;
+      final int firstLine = block.getChild( 0 ).getLine();
+      final int lastLine = block.getLastChild().getLine();
+
+      for ( int lineIndex = firstLine; lineIndex < lastLine; lineIndex++ )
+      {
+         if ( FileUtils.isLineACorrectStatement( currentFile.getLineAt( lineIndex ) ) )
+         {
+            lineNb++;
+         }
+      }
+      return lineNb;
+   }
+
+   private FunctionUtils()
+   {
+   }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRule.java b/FlexPMD/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-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/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRuleTest.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRuleTest.java b/FlexPMD/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-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/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexMetaDataRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexMetaDataRule.java b/FlexPMD/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-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/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRule.java b/FlexPMD/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-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/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRuleTest.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRuleTest.java b/FlexPMD/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-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/b0fc5f17/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractForbiddenImportRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractForbiddenImportRule.java b/FlexPMD/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-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


Mime
View raw message