You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2014/04/25 08:18:43 UTC
[44/46] FlexPMD Donation from Adobe Systems Inc
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/AS3Scanner.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/AS3Scanner.java b/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/AS3Scanner.java
new file mode 100644
index 0000000..cdd185f
--- /dev/null
+++ b/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/AS3Scanner.java
@@ -0,0 +1,898 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import com.adobe.ac.utils.StackTraceUtils;
+
+/**
+ * convert a actionscript to a stream of tokens
+ *
+ * @author rbokel
+ * @author xagnetti
+ */
+public class AS3Scanner
+{
+ /**
+ * @author xagnetti
+ */
+ public static final class Token
+ {
+ private static Token create( final String textContent,
+ final int tokenLine,
+ final int tokenColumn )
+ {
+ return new Token( textContent, tokenLine, tokenColumn );
+ }
+
+ private final int column;
+ private final boolean isNumeric;
+ private final int line;
+ private final String text;
+
+ /**
+ * @param textContent
+ * @param tokenLine
+ * @param tokenColumn
+ */
+ protected Token( final String textContent,
+ final int tokenLine,
+ final int tokenColumn )
+ {
+ this( textContent, tokenLine, tokenColumn, false );
+ }
+
+ /**
+ * @param textContent
+ * @param tokenLine
+ * @param tokenColumn
+ * @param isNumToSet
+ */
+ protected Token( final String textContent,
+ final int tokenLine,
+ final int tokenColumn,
+ final boolean isNumToSet )
+ {
+ text = textContent;
+ line = tokenLine + 1;
+ column = tokenColumn + 1;
+ isNumeric = isNumToSet;
+ }
+
+ /**
+ * @return
+ */
+ public int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * @return
+ */
+ public int getLine()
+ {
+ return line;
+ }
+
+ /**
+ * @return
+ */
+ public String getText()
+ {
+ return text;
+ }
+
+ /**
+ * @return
+ */
+ public boolean isNum()
+ {
+ return isNumeric;
+ }
+ }
+
+ private static class XMLVerifier
+ {
+ private static DefaultHandler handler;
+ private static SAXParser saxParser;
+
+ static
+ {
+ final SAXParserFactory factory = SAXParserFactory.newInstance();
+
+ handler = new DefaultHandler();
+ factory.setNamespaceAware( false );
+
+ try
+ {
+ saxParser = factory.newSAXParser();
+ }
+ catch ( final ParserConfigurationException e )
+ {
+ LOGGER.warning( StackTraceUtils.print( e ) );
+ }
+ catch ( final SAXException e )
+ {
+ }
+ }
+
+ public static boolean verify( final String text )
+ {
+ try
+ {
+ saxParser.parse( new InputSource( new StringReader( text ) ),
+ handler );
+ return true;
+ }
+ catch ( final SAXException e )
+ {
+ LOGGER.warning( StackTraceUtils.print( e ) );
+ return false;
+ }
+ catch ( final IOException e )
+ {
+ LOGGER.warning( StackTraceUtils.print( e ) );
+ return false;
+ }
+ }
+ }
+
+ private static final String END = "__END__";
+ private static final Logger LOGGER = Logger.getLogger( AS3Scanner.class.getName() );
+
+ protected static boolean isDecimalChar( final char currentCharacter )
+ {
+ return currentCharacter >= '0'
+ && currentCharacter <= '9';
+ }
+
+ private int column;
+ private boolean inVector;
+ private int line;
+ private String[] lines = null;
+
+ /**
+ * @return
+ */
+ public Token moveToNextToken()
+ {
+ return nextToken();
+ }
+
+ /**
+ * @param linesToBeSet
+ */
+ public void setLines( final String[] linesToBeSet )
+ {
+ lines = linesToBeSet;
+ line = 0;
+ column = -1;
+ }
+
+ boolean isHexChar( final char currentCharacter )
+ {
+ final boolean isNum = currentCharacter >= '0'
+ && currentCharacter <= '9';
+ final boolean isLower = currentCharacter >= 'A'
+ && currentCharacter <= 'Z';
+ final boolean isUpper = currentCharacter >= 'a'
+ && currentCharacter <= 'z';
+
+ return isNum
+ || isLower || isUpper;
+ }
+
+ /**
+ * @return
+ */
+ protected Token nextToken()
+ {
+ char currentCharacter;
+
+ if ( lines != null
+ && line < lines.length )
+ {
+ currentCharacter = nextNonWhitespaceCharacter();
+ }
+ else
+ {
+ return new Token( END, line, column );
+ }
+
+ if ( currentCharacter == '\n' )
+ {
+ return new Token( "\n", line, column );
+ }
+ if ( currentCharacter == '/' )
+ {
+ return scanCommentRegExpOrOperator();
+ }
+ if ( currentCharacter == '"' )
+ {
+ return scanString( currentCharacter );
+ }
+ if ( currentCharacter == '\'' )
+ {
+ return scanString( currentCharacter );
+ }
+ if ( currentCharacter == '<' )
+ {
+ return scanXMLOrOperator( currentCharacter );
+ }
+ if ( currentCharacter >= '0'
+ && currentCharacter <= '9' || currentCharacter == '.' )
+ {
+ return scanNumberOrDots( currentCharacter );
+ }
+ if ( currentCharacter == '{'
+ || currentCharacter == '}' || currentCharacter == '(' || currentCharacter == ')'
+ || currentCharacter == '[' || currentCharacter == ']' || currentCharacter == ';'
+ || currentCharacter == ',' || currentCharacter == '?' || currentCharacter == '~' )
+ {
+ return scanSingleCharacterToken( currentCharacter );
+ }
+ if ( currentCharacter == ':' )
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ { "::" } );
+ }
+ if ( currentCharacter == '*' )
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ {} );
+ }
+ if ( currentCharacter == '+' )
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ { "++",
+ "+=" } );
+ }
+ if ( currentCharacter == '-' )
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ { "--",
+ "-=" } );
+ }
+ if ( currentCharacter == '%' )
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ { "%=" } );
+ }
+ if ( currentCharacter == '&' )
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ { "&&",
+ "&=" } );
+ }
+ if ( currentCharacter == '|' )
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ { "||",
+ "|=" } );
+ }
+ if ( currentCharacter == '^' )
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ { "^=" } );
+ }
+ if ( currentCharacter == '>' )
+ {
+ if ( inVector )
+ {
+ inVector = false;
+ }
+ else
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ { ">>>=",
+ ">>>",
+ ">>=",
+ ">>",
+ ">=" } );
+ }
+ }
+ if ( currentCharacter == '=' )
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ { "===",
+ "==" } );
+ }
+ if ( currentCharacter == '!' )
+ {
+ return scanCharacterSequence( currentCharacter,
+ new String[]
+ { "!==",
+ "!=" } );
+ }
+
+ return scanWord( currentCharacter );
+ }
+
+ private int computePossibleMatchesMaxLength( final String[] possibleMatches )
+ {
+ int max = 0;
+
+ for ( final String possibleMatch : possibleMatches )
+ {
+ max = Math.max( max,
+ possibleMatch.length() );
+ }
+ return max;
+ }
+
+ private char getPreviousCharacter()
+ {
+ int currentIndex = -1;
+ char currentChar;
+ do
+ {
+ currentChar = peekChar( currentIndex-- );
+ }
+ while ( currentChar == ' ' );
+ return currentChar;
+ }
+
+ private boolean isIdentifierCharacter( final char currentCharacter )
+ {
+ return currentCharacter >= 'A'
+ && currentCharacter <= 'Z' || currentCharacter >= 'a' && currentCharacter <= 'z'
+ || currentCharacter >= '0' && currentCharacter <= '9' || currentCharacter == '_'
+ || currentCharacter == '$';
+ }
+
+ private boolean isProcessingInstruction( final String text )
+ {
+ return text.startsWith( "<?" );
+ }
+
+ private boolean isValidRegExp( final String pattern )
+ {
+ try
+ {
+ Pattern.compile( pattern );
+ }
+ catch ( final PatternSyntaxException t )
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isValidXML( final String text )
+ {
+ return XMLVerifier.verify( text );
+ }
+
+ private char nextChar()
+ {
+ final String currentLine = lines[ line ];
+
+ column++;
+ if ( currentLine.length() <= column )
+ {
+ column = -1;
+ line++;
+ return '\n';
+ }
+
+ char currentChar = currentLine.charAt( column );
+
+ while ( currentChar == '\uFEFF' )
+ {
+ column++;
+ currentChar = currentLine.charAt( column );
+ }
+ return currentChar;
+ }
+
+ private char nextNonWhitespaceCharacter()
+ {
+ char result;
+ do
+ {
+ result = nextChar();
+ }
+ while ( result == ' '
+ || result == '\t' );
+ return result;
+ }
+
+ private char peekChar( final int offset )
+ {
+ final String currentLine = lines[ line ];
+ final int index = column
+ + offset;
+ if ( index == -1 )
+ {
+ return '\0';
+ }
+ if ( index >= currentLine.length() )
+ {
+ return '\n';
+ }
+
+ return currentLine.charAt( index );
+ }
+
+ /**
+ * find the longest matching sequence
+ *
+ * @param currentCharacter
+ * @param possibleMatches
+ * @param maxLength
+ * @return
+ */
+ private Token scanCharacterSequence( final char currentCharacter,
+ final String[] possibleMatches )
+ {
+ int peekPos = 1;
+ final StringBuffer buffer = new StringBuffer();
+ final int maxLength = computePossibleMatchesMaxLength( possibleMatches );
+
+ buffer.append( currentCharacter );
+ String found = buffer.toString();
+ while ( peekPos < maxLength )
+ {
+ buffer.append( peekChar( peekPos ) );
+ peekPos++;
+ for ( final String possibleMatche : possibleMatches )
+ {
+ if ( buffer.toString().equals( possibleMatche ) )
+ {
+ found = buffer.toString();
+ }
+ }
+ }
+ final Token result = new Token( found, line, column );
+ skipChars( found.length() - 1 );
+ return result;
+ }
+
+ /**
+ * Something started with a slash This might be a comment, a regexp or a
+ * operator
+ *
+ * @param currentCharacter
+ * @return
+ */
+ private Token scanCommentRegExpOrOperator()
+ {
+ final char firstCharacter = peekChar( 1 );
+
+ if ( firstCharacter == '/' )
+ {
+ return scanSingleLineComment();
+ }
+ if ( firstCharacter == '*' )
+ {
+ return scanMultiLineComment();
+ }
+
+ Token result;
+
+ if ( getPreviousCharacter() == '='
+ || getPreviousCharacter() == '(' || getPreviousCharacter() == ',' )
+ {
+ result = scanRegExp();
+
+ if ( result != null )
+ {
+ return result;
+ }
+ }
+
+ if ( firstCharacter == '=' )
+ {
+ result = new Token( "/=", line, column );
+ skipChars( 1 );
+ return result;
+ }
+ result = new Token( "/", line, column );
+ return result;
+ }
+
+ /**
+ * c is either a dot or a number
+ *
+ * @return
+ */
+ private Token scanDecimal( final char currentCharacter )
+ {
+ char currentChar = currentCharacter;
+ final StringBuffer buffer = new StringBuffer();
+ int peekPos = 1;
+
+ while ( isDecimalChar( currentChar ) )
+ {
+ buffer.append( currentChar );
+ currentChar = peekChar( peekPos++ );
+ }
+
+ if ( currentChar == '.' )
+ {
+ buffer.append( currentChar );
+ currentChar = peekChar( peekPos++ );
+
+ while ( isDecimalChar( currentChar ) )
+ {
+ buffer.append( currentChar );
+ currentChar = peekChar( peekPos++ );
+ }
+
+ if ( currentChar == 'E' )
+ {
+ buffer.append( currentChar );
+ currentChar = peekChar( peekPos++ );
+ while ( isDecimalChar( currentChar ) )
+ {
+ buffer.append( currentChar );
+ currentChar = peekChar( peekPos++ );
+ }
+ }
+ }
+ final Token result = new Token( buffer.toString(), line, column, true );
+ skipChars( result.text.length() - 1 );
+ return result;
+ }
+
+ /**
+ * The first dot has been scanned Are the next chars dots as well?
+ *
+ * @return
+ */
+ private Token scanDots()
+ {
+ final char secondCharacter = peekChar( 1 );
+
+ if ( secondCharacter == '.' )
+ {
+ final char thirdCharacter = peekChar( 2 );
+ final String text = thirdCharacter == '.' ? "..."
+ : "..";
+ final Token result = new Token( text, line, column );
+
+ skipChars( text.length() - 1 );
+
+ return result;
+ }
+ else if ( secondCharacter == '<' )
+ {
+ final Token result = new Token( ".<", line, column );
+
+ skipChars( 1 );
+
+ inVector = true;
+ return result;
+ }
+ return null;
+ }
+
+ /**
+ * we have seen the 0x prefix
+ *
+ * @return
+ */
+ private Token scanHex()
+ {
+ final StringBuffer buffer = new StringBuffer();
+
+ buffer.append( "0x" );
+ int peekPos = 2;
+ for ( ;; )
+ {
+ final char character = peekChar( peekPos++ );
+
+ if ( !isHexChar( character ) )
+ {
+ break;
+ }
+ buffer.append( character );
+ }
+ final Token result = new Token( buffer.toString(), line, column, true );
+ skipChars( result.text.length() - 1 );
+ return result;
+ }
+
+ /**
+ * the current char is the first slash plus we know, that a * is following
+ *
+ * @return
+ */
+ private Token scanMultiLineComment()
+ {
+ final StringBuffer buffer = new StringBuffer();
+ char currentCharacter = ' ';
+ char previousCharacter = ' ';
+
+ buffer.append( "/*" );
+ skipChar();
+ do
+ {
+ previousCharacter = currentCharacter;
+ currentCharacter = nextChar();
+ buffer.append( currentCharacter );
+ }
+ while ( currentCharacter != 0
+ && !( currentCharacter == '/' && previousCharacter == '*' ) );
+
+ return new Token( buffer.toString(), line, column );
+ }
+
+ /**
+ * Something started with a number or a dot.
+ *
+ * @param characterToBeScanned
+ * @return
+ */
+ private Token scanNumberOrDots( final char characterToBeScanned )
+ {
+ if ( characterToBeScanned == '.' )
+ {
+ final Token result = scanDots();
+ if ( result != null )
+ {
+ return result;
+ }
+
+ final char firstCharacter = peekChar( 1 );
+ if ( !isDecimalChar( firstCharacter ) )
+ {
+ return new Token( ".", line, column );
+ }
+ }
+ if ( characterToBeScanned == '0' )
+ {
+ final char firstCharacter = peekChar( 1 );
+ if ( firstCharacter == 'x' )
+ {
+ return scanHex();
+ }
+ }
+ return scanDecimal( characterToBeScanned );
+ }
+
+ private Token scanRegExp()
+ {
+ final Token token = scanUntilDelimiter( '/' );
+ if ( token != null
+ && isValidRegExp( token.text ) )
+ {
+ return token;
+ }
+ return null;
+ }
+
+ private Token scanSingleCharacterToken( final char character )
+ {
+ return new Token( String.valueOf( character ), line, column );
+ }
+
+ /**
+ * the current char is the first slash plus we know, that another slash is
+ * following
+ *
+ * @return
+ */
+ private Token scanSingleLineComment()
+ {
+ final Token result = new Token( lines[ line ].substring( column ), line, column );
+ skipChars( result.text.length() - 1 );
+ return result;
+ }
+
+ /**
+ * Something started with a quote or double quote consume characters until
+ * the quote/double quote shows up again and is not escaped
+ *
+ * @param startingCharacter
+ * @return
+ */
+ private Token scanString( final char startingCharacter )
+ {
+ return scanUntilDelimiter( startingCharacter );
+ }
+
+ private Token scanUntilDelimiter( final char delimiter )
+ {
+ return scanUntilDelimiter( delimiter,
+ delimiter );
+
+ }
+
+ private Token scanUntilDelimiter( final char start,
+ final char delimiter )
+ {
+ final StringBuffer buffer = new StringBuffer();
+ int peekPos = 1;
+ int numberOfBackslashes = 0;
+
+ buffer.append( start );
+
+ for ( ;; )
+ {
+ final char currentCharacter = peekChar( peekPos++ );
+ if ( currentCharacter == '\n' )
+ {
+ return null;
+ }
+ buffer.append( currentCharacter );
+ if ( currentCharacter == delimiter
+ && numberOfBackslashes == 0 )
+ {
+ final Token result = Token.create( buffer.toString(),
+ line,
+ column );
+ skipChars( buffer.toString().length() - 1 );
+ return result;
+ }
+ numberOfBackslashes = currentCharacter == '\\' ? ( numberOfBackslashes + 1 ) % 2
+ : 0;
+ }
+ }
+
+ private Token scanWord( final char startingCharacter )
+ {
+ char currentChar = startingCharacter;
+ final StringBuffer buffer = new StringBuffer();
+
+ buffer.append( currentChar );
+ int peekPos = 1;
+ for ( ;; )
+ {
+ currentChar = peekChar( peekPos++ );
+ if ( !isIdentifierCharacter( currentChar ) )
+ {
+ break;
+ }
+
+ buffer.append( currentChar );
+ }
+ final Token result = new Token( buffer.toString(), line, column );
+ skipChars( buffer.toString().length() - 1 );
+ return result;
+ }
+
+ /**
+ * Try to parse a XML document
+ *
+ * @return
+ */
+ private Token scanXML()
+ {
+ final int currentLine = line;
+ final int currentColumn = column;
+ int level = 0;
+ final StringBuffer buffer = new StringBuffer();
+ char currentCharacter = '<';
+
+ for ( ;; )
+ {
+ Token currentToken = null;
+ do
+ {
+ currentToken = scanUntilDelimiter( '<',
+ '>' );
+ if ( currentToken == null )
+ {
+ line = currentLine;
+ column = currentColumn;
+ return null;
+ }
+ buffer.append( currentToken.text );
+ if ( isProcessingInstruction( currentToken.text ) )
+ {
+ currentCharacter = nextChar();
+ if ( currentCharacter == '\n' )
+ {
+ buffer.append( '\n' );
+ skipChar();
+ }
+ currentToken = null;
+ }
+ }
+ while ( currentToken == null );
+
+ if ( currentToken.text.startsWith( "</" ) )
+ {
+ level--;
+ }
+ else if ( !currentToken.text.endsWith( "/>" )
+ && !currentToken.text.equals( "<>" ) ) // NOT operator in AS2
+ {
+ level++;
+ }
+
+ if ( level <= 0 )
+ {
+ return new Token( buffer.toString(), line, column );
+ }
+
+ for ( ;; )
+ {
+ currentCharacter = nextChar();
+ if ( currentCharacter == '<' )
+ {
+ break;
+ }
+ buffer.append( currentCharacter );
+ }
+ }
+ }
+
+ /**
+ * Something started with a lower sign <
+ *
+ * @param startingCharacterc
+ * @return
+ */
+ private Token scanXMLOrOperator( final char startingCharacterc )
+ {
+ final Token xmlToken = scanXML();
+
+ if ( xmlToken != null
+ && isValidXML( xmlToken.text ) )
+ {
+ return xmlToken;
+ }
+ return scanCharacterSequence( startingCharacterc,
+ new String[]
+ { "<<<=",
+ "<<<",
+ "<<=",
+ "<<",
+ "<=" } );
+ }
+
+ private void skipChar()
+ {
+ nextChar();
+ }
+
+ private void skipChars( final int count )
+ {
+ int decrementCount = count;
+
+ while ( decrementCount-- > 0 )
+ {
+ nextChar();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/NestedNode.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/NestedNode.java b/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/NestedNode.java
new file mode 100644
index 0000000..27affb2
--- /dev/null
+++ b/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/NestedNode.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 de.bokelberg.flex.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.adobe.ac.pmd.parser.IParserNode;
+import com.adobe.ac.pmd.parser.NodeKind;
+
+/**
+ * @author xagnetti
+ */
+class NestedNode
+{
+ private List< IParserNode > children;
+ private NodeKind nodeId;
+
+ /**
+ * @param idToBeSet
+ */
+ protected NestedNode( final NodeKind idToBeSet )
+ {
+ nodeId = idToBeSet;
+ }
+
+ /**
+ * @param idToBeSet
+ * @param childToBeSet
+ */
+ protected NestedNode( final NodeKind idToBeSet,
+ final IParserNode childToBeSet )
+ {
+ this( idToBeSet );
+ addChild( childToBeSet );
+ }
+
+ /**
+ * @return
+ */
+ public final int computeCyclomaticComplexity()
+ {
+ int cyclomaticComplexity = 0;
+
+ if ( is( NodeKind.FOREACH )
+ || is( NodeKind.FORIN ) || is( NodeKind.CASE ) || is( NodeKind.DEFAULT ) )
+ {
+ cyclomaticComplexity++;
+ }
+ else if ( is( NodeKind.IF )
+ || is( NodeKind.WHILE ) || is( NodeKind.FOR ) )
+ {
+ cyclomaticComplexity++;
+ cyclomaticComplexity += getChild( 0 ).countNodeFromType( NodeKind.AND );
+ cyclomaticComplexity += getChild( 0 ).countNodeFromType( NodeKind.OR );
+ }
+
+ if ( numChildren() > 0 )
+ {
+ for ( final IParserNode child : getChildren() )
+ {
+ cyclomaticComplexity += child.computeCyclomaticComplexity();
+ }
+ }
+
+ return cyclomaticComplexity;
+ }
+
+ /**
+ * @param type
+ * @return
+ */
+ public final int countNodeFromType( final NodeKind type )
+ {
+ int count = 0;
+
+ if ( is( type ) )
+ {
+ count++;
+ }
+ if ( numChildren() > 0 )
+ {
+ for ( final IParserNode child : getChildren() )
+ {
+ count += child.countNodeFromType( type );
+ }
+ }
+ return count;
+ }
+
+ /**
+ * @param index
+ * @return
+ */
+ public final IParserNode getChild( final int index )
+ {
+ return getChildren() == null
+ || getChildren().size() <= index ? null
+ : getChildren().get( index );
+ }
+
+ /**
+ * @return
+ */
+ public List< IParserNode > getChildren()
+ {
+ return children;
+ }
+
+ /**
+ * @return
+ */
+ public NodeKind getId()
+ {
+ return nodeId;
+ }
+
+ /**
+ * @return
+ */
+ public IParserNode getLastChild()
+ {
+ final IParserNode lastChild = getChild( numChildren() - 1 );
+
+ return lastChild != null
+ && lastChild.numChildren() > 0 ? lastChild.getLastChild()
+ : lastChild;
+ }
+
+ /**
+ * @param expectedType
+ * @return
+ */
+ public final boolean is( final NodeKind expectedType ) // NOPMD
+ {
+ return getId().equals( expectedType );
+ }
+
+ /**
+ * @return
+ */
+ public final int numChildren()
+ {
+ return getChildren() == null ? 0
+ : getChildren().size();
+ }
+
+ /**
+ * @param child
+ * @return
+ */
+ final IParserNode addChild( final IParserNode child )
+ {
+ if ( child == null )
+ {
+ return child; // skip optional children
+ }
+
+ if ( children == null )
+ {
+ children = new ArrayList< IParserNode >();
+ }
+ children.add( child );
+ return child;
+ }
+
+ /**
+ * @param childId
+ * @param childLine
+ * @param childColumn
+ * @param nephew
+ * @return
+ */
+ final IParserNode addChild( final NodeKind childId,
+ final int childLine,
+ final int childColumn,
+ final IParserNode nephew )
+ {
+ return addChild( Node.create( childId,
+ childLine,
+ childColumn,
+ nephew ) );
+ }
+
+ /**
+ * @param childId
+ * @param childLine
+ * @param childColumn
+ * @param value
+ * @return
+ */
+ final IParserNode addChild( final NodeKind childId,
+ final int childLine,
+ final int childColumn,
+ final String value )
+ {
+ return addChild( Node.create( childId,
+ childLine,
+ childColumn,
+ value ) );
+ }
+
+ /**
+ * @param idToBeSet
+ */
+ final void setId( final NodeKind idToBeSet )
+ {
+ nodeId = idToBeSet;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/Node.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/Node.java b/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/Node.java
new file mode 100644
index 0000000..a044881
--- /dev/null
+++ b/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/Node.java
@@ -0,0 +1,168 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.adobe.ac.pmd.parser.IParserNode;
+import com.adobe.ac.pmd.parser.NodeKind;
+
+/**
+ * A single node of the ast
+ *
+ * @author rbokel
+ */
+final class Node extends NestedNode implements IParserNode
+{
+ protected static Node create( final NodeKind idToBeSet,
+ final int lineToBeSet,
+ final int columnToBeSet )
+ {
+ return new Node( idToBeSet, lineToBeSet, columnToBeSet );
+ }
+
+ protected static Node create( final NodeKind idToBeSet,
+ final int lineToBeSet,
+ final int columnToBeSet,
+ final IParserNode childToBeSet )
+ {
+ return new Node( idToBeSet, lineToBeSet, columnToBeSet, childToBeSet );
+ }
+
+ protected static Node create( final NodeKind idToBeSet,
+ final int lineToBeSet,
+ final int columnToBeSet,
+ final String valueToBeSet )
+ {
+ return new Node( idToBeSet, lineToBeSet, columnToBeSet, valueToBeSet );
+ }
+
+ private static boolean isNameInArray( final String[] strings,
+ final String string )
+ {
+ for ( final String currentName : strings )
+ {
+ if ( currentName.equals( string ) )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private final int column;
+ private final int line;
+ private final String stringValue;
+
+ private Node( final NodeKind idToBeSet,
+ final int lineToBeSet,
+ final int columnToBeSet )
+ {
+ super( idToBeSet );
+
+ line = lineToBeSet;
+ column = columnToBeSet;
+ stringValue = null;
+ }
+
+ private Node( final NodeKind idToBeSet,
+ final int lineToBeSet,
+ final int columnToBeSet,
+ final IParserNode childToBeSet )
+ {
+ super( idToBeSet, childToBeSet );
+
+ line = lineToBeSet;
+ column = columnToBeSet;
+ stringValue = null;
+ }
+
+ private Node( final NodeKind idToBeSet,
+ final int lineToBeSet,
+ final int columnToBeSet,
+ final String valueToBeSet )
+ {
+ super( idToBeSet );
+
+ line = lineToBeSet;
+ column = columnToBeSet;
+ stringValue = valueToBeSet;
+ }
+
+ public List< IParserNode > findPrimaryStatementsFromNameInChildren( final String[] names )
+ {
+ final List< IParserNode > foundNode = new ArrayList< IParserNode >();
+
+ if ( getStringValue() != null
+ && isNameInArray( names,
+ getStringValue() ) )
+ {
+ foundNode.add( this );
+ }
+ else if ( numChildren() != 0 )
+ {
+ for ( final IParserNode child : getChildren() )
+ {
+ foundNode.addAll( child.findPrimaryStatementsFromNameInChildren( names ) );
+ }
+ }
+ return foundNode;
+ }
+
+ public int getColumn()
+ {
+ return column;
+ }
+
+ public int getLine()
+ {
+ return line;
+ }
+
+ public String getStringValue()
+ {
+ return stringValue;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuffer buffer = new StringBuffer();
+
+ if ( getStringValue() == null )
+ {
+ buffer.append( getId() );
+ }
+ else
+ {
+ buffer.append( getStringValue() );
+ }
+
+ buffer.append( ' ' );
+
+ if ( getChildren() != null )
+ {
+ for ( final IParserNode child : getChildren() )
+ {
+ buffer.append( child.toString() );
+ buffer.append( ' ' );
+ }
+ }
+ return buffer.toString();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/AbstractAs3ParserTest.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/AbstractAs3ParserTest.java b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/AbstractAs3ParserTest.java
new file mode 100644
index 0000000..ff9b895
--- /dev/null
+++ b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/AbstractAs3ParserTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import junit.framework.TestCase;
+
+import org.junit.Before;
+
+import com.adobe.ac.pmd.parser.IParserNode;
+
+public abstract class AbstractAs3ParserTest extends TestCase
+{
+ protected final class ASTToXMLConverter
+ {
+ public String convert( final IParserNode ast )
+ {
+ final StringBuffer result = new StringBuffer();
+ visitNodes( ast,
+ result,
+ 0 );
+ return result.toString();
+ }
+ }
+
+ private static String escapeEntities( final String stringToEscape )
+ {
+ final StringBuffer buffer = new StringBuffer();
+
+ for ( int i = 0; i < stringToEscape.length(); i++ )
+ {
+ final char currentCharacter = stringToEscape.charAt( i );
+
+ if ( currentCharacter == '<' )
+ {
+ buffer.append( "<" );
+ }
+ else if ( currentCharacter == '>' )
+ {
+ buffer.append( ">" );
+ }
+ else
+ {
+ buffer.append( currentCharacter );
+ }
+ }
+ return buffer.toString();
+ }
+
+ private static void visitNodes( final IParserNode ast,
+ final StringBuffer result,
+ final int level )
+ {
+ result.append( "<"
+ + ast.getId() + " line=\"" + ast.getLine() + "\">" );
+
+ final int numChildren = ast.numChildren();
+ if ( numChildren > 0 )
+ {
+ for ( int i = 0; i < numChildren; i++ )
+ {
+ visitNodes( ast.getChild( i ),
+ result,
+ level + 1 );
+ }
+ }
+ else if ( ast.getStringValue() != null )
+ {
+ result.append( escapeEntities( ast.getStringValue() ) );
+ }
+ result.append( "</"
+ + ast.getId() + ">" );
+ }
+
+ protected AS3Parser asp;
+ protected AS3Scanner scn;
+
+ @Override
+ @Before
+ public void setUp()
+ {
+ asp = new AS3Parser();
+ scn = asp.getScn();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/AbstractStatementTest.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/AbstractStatementTest.java b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/AbstractStatementTest.java
new file mode 100644
index 0000000..b437833
--- /dev/null
+++ b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/AbstractStatementTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import com.adobe.ac.pmd.parser.exceptions.TokenException;
+
+public abstract class AbstractStatementTest extends AbstractAs3ParserTest
+{
+ protected void assertStatement( final String message,
+ final String input,
+ final String expected ) throws TokenException
+ {
+ scn.setLines( new String[]
+ { input,
+ "__END__" } );
+ asp.nextToken();
+ final String result = new ASTToXMLConverter().convert( asp.parseStatement() );
+ assertEquals( message,
+ expected,
+ result );
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/NestedNodeTest.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/NestedNodeTest.java b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/NestedNodeTest.java
new file mode 100644
index 0000000..7d547ef
--- /dev/null
+++ b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/NestedNodeTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.adobe.ac.pmd.parser.NodeKind;
+import com.adobe.ac.pmd.parser.exceptions.TokenException;
+
+public class NestedNodeTest extends AbstractAs3ParserTest
+{
+ private NestedNode function;
+
+ @Override
+ @Before
+ public void setUp()
+ {
+ super.setUp();
+
+ final String code = "public function foo() : void {"
+ + "while(i>0){" + "while(true){" + "switch(a){" + "case 1:break;default:return;" + "}" + "}"
+ + "}" + "}";
+ final Node classNode = parseClass( code );
+
+ function = ( Node ) classNode.getChild( 0 );
+ }
+
+ @Test
+ public void testComputeCyclomaticComplexity()
+ {
+ assertEquals( 5,
+ function.computeCyclomaticComplexity() );
+ }
+
+ @Test
+ public void testCountNodeFromType()
+ {
+ assertEquals( 2,
+ function.countNodeFromType( NodeKind.WHILE ) );
+ }
+
+ @Test
+ public void testGetLastChild()
+ {
+ assertEquals( NodeKind.RETURN,
+ function.getLastChild().getId() );
+
+ assertNull( function.getChild( Integer.MAX_VALUE ) );
+ }
+
+ @Test
+ public void testIs()
+ {
+ assertFalse( function.is( null ) );
+ }
+
+ private Node parseClass( final String input )
+ {
+ scn.setLines( new String[]
+ { "{",
+ input,
+ "}",
+ "__END__" } );
+ try
+ {
+ asp.nextToken();
+ asp.nextToken(); // skip {
+ return asp.parseClassContent();
+ }
+ catch ( final TokenException e )
+ {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/NodeTest.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/NodeTest.java b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/NodeTest.java
new file mode 100644
index 0000000..cf7dae1
--- /dev/null
+++ b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/NodeTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import org.junit.Test;
+
+import com.adobe.ac.pmd.parser.exceptions.TokenException;
+
+public class NodeTest extends AbstractAs3ParserTest
+{
+ @Test
+ public void testFindPrimaryStatementsFromNameInChildren() throws TokenException
+ {
+ final Node ast = parseFunction( "function set a( value : int ) : void { trace(\"lala\")}" );
+
+ assertEquals( 2,
+ ast.findPrimaryStatementsFromNameInChildren( new String[]
+ { "trace",
+ "\"lala\"" } ).size() );
+ }
+
+ @Test
+ public void testToString() throws TokenException
+ {
+ final Node ast = parseFunction( "function set a( value : int ) : void { trace(\"lala\")}" );
+
+ assertEquals( "content set mod-list a parameter-list parameter name-type-init "
+ + "value int void block call trace arguments \"lala\" ",
+ ast.toString() );
+ }
+
+ private Node parseFunction( final String input ) throws TokenException
+ {
+ scn.setLines( new String[]
+ { "{",
+ input,
+ "}",
+ "__END__" } );
+ asp.nextToken(); // first call
+ asp.nextToken(); // skip {
+ return asp.parseClassContent();
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3Parser.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3Parser.java b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3Parser.java
new file mode 100644
index 0000000..44738f1
--- /dev/null
+++ b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3Parser.java
@@ -0,0 +1,75 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import org.junit.Test;
+
+import com.adobe.ac.pmd.files.impl.FileUtils;
+import com.adobe.ac.pmd.parser.IParserNode;
+import com.adobe.ac.pmd.parser.exceptions.TokenException;
+
+public class TestAS3Parser extends AbstractAs3ParserTest
+{
+ @Test
+ public void testBuildAst() throws IOException,
+ URISyntaxException,
+ TokenException
+ {
+ asp.buildAst( getClass().getResource( "/examples/unformatted/IContext.as" ).toURI().getPath() );
+ asp.buildAst( getClass().getResource( "/examples/FlexPMD115.as" ).toURI().getPath() );
+ asp.buildAst( getClass().getResource( "/examples/JPEGEncoder.as" ).toURI().getPath() );
+ asp.buildAst( getClass().getResource( "/examples/JPEGEncoder2.as" ).toURI().getPath() );
+ asp.buildAst( getClass().getResource( "/examples/FisheyeBase.as" ).toURI().getPath() );
+ asp.buildAst( getClass().getResource( "/examples/FlexPMD98.as" ).toURI().getPath() );
+ asp.buildAst( getClass().getResource( "/examples/FlexPMD195.as" ).toURI().getPath() );
+ final String titlePath = getClass().getResource( "/examples/unformatted/Title.as" ).toURI().getPath();
+
+ asp.buildAst( titlePath );
+ asp.buildAst( titlePath,
+ FileUtils.readLines( new File( titlePath ) ) );
+ }
+
+ @Test
+ public void testBuildAst_AS2() throws IOException,
+ URISyntaxException,
+ TokenException
+ {
+ asp.buildAst( getClass().getResource( "/examples/toAS2/src/fw/data/request/ResultListener.as" )
+ .toURI()
+ .getPath() );
+
+ asp.buildAst( getClass().getResource( "/examples/toAS2/src/epg/StateExit_AS2.as" ).toURI().getPath() );
+ }
+
+ @Test
+ public void testBuildAst2() throws IOException,
+ TokenException,
+ URISyntaxException
+ {
+ final IParserNode flexPmd62 = asp.buildAst( getClass().getResource( "/examples/FlexPMD62.as" )
+ .toURI()
+ .getPath() );
+
+ assertEquals( "com.test.testy.ui.components",
+ flexPmd62.getChild( 0 ).getChild( 0 ).getStringValue() );
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3Scanner.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3Scanner.java b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3Scanner.java
new file mode 100644
index 0000000..240b354
--- /dev/null
+++ b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3Scanner.java
@@ -0,0 +1,362 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import org.junit.Test;
+
+import de.bokelberg.flex.parser.AS3Scanner.Token;
+
+public class TestAS3Scanner extends AbstractAs3ParserTest
+{
+ @Test
+ public void testAssignments()
+ {
+ final String[] lines = new String[]
+ { "=",
+ "+=",
+ "-=",
+ "%=",
+ "^=",
+ "&=",
+ "|=",
+ "/=" };
+ scn.setLines( lines );
+
+ for ( int i = 0; i < lines.length; i++ )
+ {
+ assertText( Integer.toString( i ),
+ lines[ i ] );
+ assertText( "\n" );
+ }
+ }
+
+ @Test
+ public void testBooleanOperators()
+ {
+ final String[] lines = new String[]
+ { "&&",
+ "&=",
+ "||",
+ "|=" };
+ scn.setLines( lines );
+
+ for ( int i = 0; i < lines.length; i++ )
+ {
+ assertText( Integer.toString( i ),
+ lines[ i ] );
+ assertText( "\n" );
+ }
+ }
+
+ @Test
+ public void testComparisonOperators()
+ {
+ final String[] lines = new String[]
+ { ">",
+ ">>>=",
+ ">>>",
+ ">>=",
+ ">>",
+ ">=",
+ "===",
+ "==",
+ "!==",
+ "!=" };
+ scn.setLines( lines );
+
+ for ( int i = 0; i < lines.length; i++ )
+ {
+ assertText( Integer.toString( i ),
+ lines[ i ] );
+ assertText( "\n" );
+ }
+ }
+
+ @Test
+ public void testIdentifiers()
+ {
+ final String[] lines = new String[]
+ { "a",
+ "a.b.*",
+ "a.b::c",
+ "a.E" };
+ scn.setLines( lines );
+
+ assertText( "1",
+ lines[ 0 ] );
+ assertText( "\n" );
+
+ assertText( "2",
+ "a" );
+ assertText( "2",
+ "." );
+ assertText( "2",
+ "b" );
+ assertText( "2",
+ "." );
+ assertText( "2",
+ "*" );
+ assertText( "\n" );
+
+ assertText( "3",
+ "a" );
+ assertText( "3",
+ "." );
+ assertText( "3",
+ "b" );
+ assertText( "3",
+ "::" );
+ assertText( "3",
+ "c" );
+ assertText( "\n" );
+
+ assertText( "4",
+ "a" );
+ assertText( "4",
+ "." );
+ assertText( "4",
+ "E" );
+ }
+
+ @Test
+ public void testIsDecimalChar()
+ {
+ final String decimalString = "0123456789";
+ for ( int i = 0; i < decimalString.length(); i++ )
+ {
+ assertTrue( "",
+ AS3Scanner.isDecimalChar( decimalString.charAt( i ) ) );
+ }
+ assertFalse( "",
+ AS3Scanner.isDecimalChar( ( char ) 0 ) );
+
+ }
+
+ @Test
+ public void testIsHex()
+ {
+ assertTrue( "",
+ scn.isHexChar( '0' ) );
+ assertTrue( "",
+ scn.isHexChar( '9' ) );
+ assertTrue( "",
+ scn.isHexChar( 'A' ) );
+ assertTrue( "",
+ scn.isHexChar( 'a' ) );
+ assertTrue( "",
+ scn.isHexChar( 'F' ) );
+ assertTrue( "",
+ scn.isHexChar( 'f' ) );
+ assertFalse( "",
+ scn.isHexChar( ';' ) );
+ assertFalse( "",
+ scn.isHexChar( ']' ) );
+ assertFalse( "",
+ scn.isHexChar( ' ' ) );
+ }
+
+ @Test
+ public void testMultiLineComment()
+ {
+ final String[] lines = new String[]
+ { "/* this is a multi line comment, not really */",
+ "/** now for real",
+ "/* now for real",
+ "*/" };
+ scn.setLines( lines );
+
+ assertText( lines[ 0 ] );
+ assertText( "\n" );
+ assertText( "/** now for real\n/* now for real\n*/" );
+ }
+
+ @Test
+ public void testMultilineXML()
+ {
+ final String[] lines = new String[]
+ { "<?xml version=\"1.0\"?>",
+ "<a>",
+ "<b>test</b>",
+ "</a>" };
+ scn.setLines( lines );
+ assertText( join( lines,
+ "\n" ) );
+ }
+
+ @Test
+ public void testMultipleWords()
+ {
+ final String[] lines = new String[]
+ { "word1 word2 word3",
+ "word4",
+ "word5 word6" };
+ scn.setLines( lines );
+
+ assertText( "word1" );
+ assertText( "word2" );
+ assertText( "word3" );
+ assertText( "\n" );
+ assertText( "word4" );
+ assertText( "\n" );
+ assertText( "word5" );
+ assertText( "word6" );
+ }
+
+ @Test
+ public void testNumbers()
+ {
+ final String[] lines = new String[]
+ { "0",
+ "1.2",
+ "1.2E5",
+ "0xffgg" };
+ scn.setLines( lines );
+
+ assertText( lines[ 0 ] );
+ assertText( "\n" );
+ assertText( lines[ 1 ] );
+ assertText( "\n" );
+ assertText( lines[ 2 ] );
+ assertText( "\n" );
+ assertText( lines[ 3 ] );
+ }
+
+ @Test
+ public void testPlusSymbols()
+ {
+ final String[] lines = new String[]
+ { "++",
+ "+=",
+ "+",
+ "--",
+ "-=",
+ "-" };
+ scn.setLines( lines );
+
+ for ( int i = 0; i < lines.length; i++ )
+ {
+ assertText( Integer.toString( i ),
+ lines[ i ] );
+ assertText( "\n" );
+ }
+ }
+
+ @Test
+ public void testSingleCharacterSymbols()
+ {
+ final String[] lines = "{}()[]:;,?~".split( "" );
+ scn.setLines( lines );
+
+ // the first entry is empty, so we skip it
+ for ( int i = 1; i < lines.length; i++ )
+ {
+ assertText( "\n" );
+ assertText( Integer.toString( i ),
+ lines[ i ] );
+ }
+ }
+
+ @Test
+ public void testSingleLineComment()
+ {
+ final String[] lines = new String[]
+ { "//this is a single line comment",
+ "word //another single line comment" };
+ scn.setLines( lines );
+
+ assertText( lines[ 0 ] );
+ assertText( "\n" );
+ assertText( "word" );
+ assertText( "//another single line comment" );
+ }
+
+ @Test
+ public void testSingleWord()
+ {
+ final String[] lines = new String[]
+ { "word" };
+ scn.setLines( lines );
+
+ assertText( lines[ 0 ] );
+ }
+
+ @Test
+ public void testStrings()
+ {
+ final String[] lines = new String[]
+ { "\"string\"",
+ "\'string\'",
+ "\"string\\\"\"" };
+ scn.setLines( lines );
+
+ assertText( "1",
+ lines[ 0 ] );
+ assertText( "\n" );
+ assertText( "2",
+ lines[ 1 ] );
+ assertText( "\n" );
+ assertText( "3",
+ lines[ 2 ] );
+ }
+
+ @Test
+ public void testXML()
+ {
+ final String[] lines = new String[]
+ { "<root/>",
+ "<root>test</root>",
+ "<?xml version=\"1.0\"?><root>test</root>" };
+ scn.setLines( lines );
+ for ( int i = 0; i < lines.length; i++ )
+ {
+ assertText( Integer.toString( i ),
+ lines[ i ] );
+ assertText( "\n" );
+ }
+ }
+
+ private void assertText( final String text )
+ {
+ assertText( "",
+ text );
+ }
+
+ private void assertText( final String message,
+ final String text )
+ {
+ Token tokent = null;
+ tokent = scn.nextToken();
+ assertEquals( message,
+ text,
+ tokent.getText() );
+ }
+
+ private String join( final String[] lines,
+ final String delimiter )
+ {
+ final StringBuffer result = new StringBuffer();
+ for ( int i = 0; i < lines.length; i++ )
+ {
+ if ( i > 0 )
+ {
+ result.append( delimiter );
+ }
+ result.append( lines[ i ] );
+ }
+ return result.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3ScannerWithFiles.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3ScannerWithFiles.java b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3ScannerWithFiles.java
new file mode 100644
index 0000000..d101579
--- /dev/null
+++ b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestAS3ScannerWithFiles.java
@@ -0,0 +1,92 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import org.junit.Test;
+
+import com.adobe.ac.pmd.files.impl.FileUtils;
+
+import de.bokelberg.flex.parser.AS3Scanner.Token;
+
+public class TestAS3ScannerWithFiles extends AbstractAs3ParserTest
+{
+ @Test
+ public void testSimple() throws IOException,
+ URISyntaxException
+ {
+ final String[] expected = new String[]
+ { "package",
+ "simple",
+ "{",
+ "public",
+ "class",
+ "Simple",
+ "{",
+ "public",
+ "function",
+ "Simple",
+ "(",
+ ")",
+ "{",
+ "trace",
+ "(",
+ "\"Simple\"",
+ ")",
+ ";",
+ "}",
+ "}" };
+ assertFile( expected,
+ "Simple.as" );
+ }
+
+ private void assertFile( final String[] expected,
+ final String fileName ) throws IOException,
+ URISyntaxException
+ {
+ final String[] lines = FileUtils.readLines( new File( getClass().getResource( "/examples/unformatted/" )
+ .toURI()
+ .getPath()
+ + fileName ) );
+ assertLines( expected,
+ lines );
+ }
+
+ private void assertLines( final String[] expected,
+ final String[] lines )
+ {
+ scn.setLines( lines );
+ for ( int i = 0; i < expected.length; i++ )
+ {
+ assertText( Integer.toString( i ),
+ expected[ i ] );
+ }
+ }
+
+ private void assertText( final String message,
+ final String text )
+ {
+ Token token = null;
+ token = scn.nextToken();
+ assertEquals( message,
+ text,
+ token.getText() );
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestClass.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestClass.java b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestClass.java
new file mode 100644
index 0000000..54235ef
--- /dev/null
+++ b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestClass.java
@@ -0,0 +1,144 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import org.junit.Test;
+
+import com.adobe.ac.pmd.parser.exceptions.TokenException;
+
+public class TestClass extends AbstractAs3ParserTest
+{
+ @Test
+ public void testExtends() throws TokenException
+ {
+ assertPackageContent( "1",
+ "public class A extends B { } ",
+ "<content line=\"2\">"
+ + "<class line=\"2\">" + "<name line=\"2\">A</name><mod-list line=\"2\">"
+ + "<mod line=\"2\">public</mod></mod-list><extends line=\"2\""
+ + ">B</extends><content line=\"2\"></content>" + "</class></content>" );
+
+ assertPackageContent( "1",
+ "public class A extends com.adobe::B { } ",
+ "<content line=\"2\"><class line=\"2\"><name line=\"2\""
+ + ">A</name><mod-list line=\"2\"><mod line=\"2\""
+ + ">public</mod></mod-list><extends line=\"2\""
+ + ">com.adobe::B</extends><content line=\"2\"></content>"
+ + "</class></content>" );
+ }
+
+ @Test
+ public void testFinalClass() throws TokenException
+ {
+ assertPackageContent( "",
+ "public final class Title{ }",
+ "<content line=\"2\">"
+ + "<class line=\"2\">" + "<name line=\"2\">Title</name>"
+ + "<mod-list line=\"2\">" + "<mod line=\"2\">public</mod>"
+ + "<mod line=\"2\">final</mod></mod-list>" + "<content line=\"2\""
+ + "></content>" + "</class>" + "</content>" );
+ }
+
+ @Test
+ public void testFullFeatured() throws TokenException
+ {
+ // assertPackageContent( "",
+ // "public class A { public static const RULE_REMOVED : String = \"ruleRemoved\";}",
+ // "" );
+
+ assertPackageContent( "1",
+ "public class A extends B implements C,D { } ",
+ "<content line=\"2\"><class line=\"2\">"
+ + "<name line=\"2\">A</name><mod-list line=\"2\">"
+ + "<mod line=\"2\">public</mod></mod-list><extends line=\"2\""
+ + ">B</extends><implements-list line=\"2\">"
+ + "<implements line=\"2\">C</implements><implements line=\"2\""
+ + ">D</implements></implements-list><content line=\"2\">"
+ + "</content></class></content>" );
+ }
+
+ @Test
+ public void testImplementsList() throws TokenException
+ {
+ assertPackageContent( "1",
+ "public class A implements B,C { } ",
+ "<content line=\"2\"><class line=\"2\">"
+ + "<name line=\"2\">A</name><mod-list line=\"2\""
+ + "><mod line=\"2\">public</mod></mod-list>"
+ + "<implements-list line=\"2\"><implements line=\"2\""
+ + ">B</implements><implements line=\"2\">"
+ + "C</implements></implements-list><content line=\"2\">"
+ + "</content></class></content>" );
+ }
+
+ @Test
+ public void testImplementsSingle() throws TokenException
+ {
+ assertPackageContent( "1",
+ "public class A implements B { } ",
+ "<content line=\"2\"><class line=\"2\">"
+ + "<name line=\"2\">A</name><mod-list line=\"2\""
+ + "><mod line=\"2\">public</mod></mod-list>"
+ + "<implements-list line=\"2\"><implements line=\"2\""
+ + ">B</implements></implements-list><content line=\"2\""
+ + "></content></class></content>" );
+ }
+
+ @Test
+ public void testImportInsideClass() throws TokenException
+ {
+ assertPackageContent( "",
+ "public final class Title{ import lala.lala; }",
+ "<content line=\"2\">"
+ + "<class line=\"2\"><name line=\"2\">Title</name>"
+ + "<mod-list line=\"2\"><mod line=\"2\">public</mod>"
+ + "<mod line=\"2\">final</mod></mod-list>"
+ + "<content line=\"2\"><import line=\"2\""
+ + ">lala.lala</import></content></class></content>" );
+
+ }
+
+ @Test
+ public void testInclude() throws TokenException
+ {
+ assertPackageContent( "1",
+ "public class A extends B { include \"ITextFieldInterface.asz\" } ",
+ "<content line=\"2\"><class line=\"2\">"
+ + "<name line=\"2\">A</name><mod-list line=\"2\">"
+ + "<mod line=\"2\">public</mod></mod-list>"
+ + "<extends line=\"2\">B</extends>"
+ + "<content line=\"2\"></content></class></content>" );
+ }
+
+ private void assertPackageContent( final String message,
+ final String input,
+ final String expected ) throws TokenException
+ {
+ scn.setLines( new String[]
+ { "{",
+ input,
+ "}",
+ "__END__" } );
+ asp.nextToken(); // first call
+ asp.nextToken(); // skip {
+ final String result = new ASTToXMLConverter().convert( asp.parsePackageContent() );
+ assertEquals( message,
+ expected,
+ result );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestClassContent.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestClassContent.java b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestClassContent.java
new file mode 100644
index 0000000..79b767d
--- /dev/null
+++ b/FlexPMD/as3-parser/src/test/java/de/bokelberg/flex/parser/TestClassContent.java
@@ -0,0 +1,307 @@
+/*
+ * 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 de.bokelberg.flex.parser;
+
+import org.junit.Test;
+
+import com.adobe.ac.pmd.parser.exceptions.TokenException;
+
+public class TestClassContent extends AbstractAs3ParserTest
+{
+ @Test
+ public void testCommentInMethod() throws TokenException
+ {
+ assertClassContent( "",
+ "public function log():void{/* comment */}",
+ "<function line=\"2\"><mod-list line=\"2\"><mod "
+ + "line=\"2\">public</mod></mod-list><name line=\"2\">log</name>"
+ + "<parameter-list line=\"2\"></parameter-list><type line=\"2\">"
+ + "void</type><block line=\"2\"><multi-line-comment line=\"2\">"
+ + "/* comment */</multi-line-comment></block></function>" );
+
+ assertClassContent( "",
+ new String[]
+ { "{",
+ "public function log():void{// comment ",
+ "}",
+ "}",
+ "__END__" },
+ "<function line=\"2\"><mod-list line=\"2\"><mod line=\"2\""
+ + ">public</mod></mod-list><name line=\"2\">log</name>"
+ + "<parameter-list line=\"2\"></parameter-list><type line=\"2\""
+ + ">void</type><block line=\"2\"></block></function>" );
+ }
+
+ @Test
+ public void testConstDeclarations() throws TokenException
+ {
+ assertClassContent( "1",
+ "const a",
+ "<const-list line=\"2\"><mod-list line=\"2\">"
+ + "</mod-list><name-type-init line=\"2\"><name line=\"2\">a"
+ + "</name><type line=\"3\"></type></name-type-init></const-list>" );
+
+ assertClassContent( "2",
+ "public const a",
+ "<const-list line=\"2\"><mod-list line=\"2\">"
+ + "<mod line=\"2\">public</mod></mod-list><name-type-init line=\"2\""
+ + "><name line=\"2\">a</name><type line=\"3\">"
+ + "</type></name-type-init></const-list>" );
+
+ assertClassContent( "3",
+ "public static const a : int = 0",
+ "<const-list line=\"2\"><mod-list line=\"2\">"
+ + "<mod line=\"2\">public</mod><mod line=\"2\">"
+ + "static</mod></mod-list><name-type-init line=\"2\"><name "
+ + "line=\"2\">a</name><type line=\"2\">int</type>"
+ + "<init line=\"2\"><primary line=\"2\">0</primary>"
+ + "</init></name-type-init></const-list>" );
+
+ assertClassContent( "4",
+ "[Bindable] const a",
+ "<const-list line=\"2\"><meta-list line=\"2\">"
+ + "<meta line=\"2\">Bindable</meta></meta-list><mod-list line=\"2\""
+ + "></mod-list><name-type-init line=\"2\">"
+ + "<name line=\"2\">a</name><type line=\"3\">"
+ + "</type></name-type-init></const-list>" );
+ }
+
+ @Test
+ public void testFlexPMD211() throws TokenException
+ {
+ assertClassContent( "",
+ "private function foo(sf:int):void{"
+ + "var a:Vector.<String> = new Vector.<String>()}",
+ "<function line=\"2\"><mod-list line=\"2\"><mod line=\"2\">private</mod>"
+ + "</mod-list><name line=\"2\">foo</name><parameter-list line=\"2\">"
+ + "<parameter line=\"2\"><name-type-init line=\"2\"><name line=\"2\">sf</name>"
+ + "<type line=\"2\">int</type></name-type-init></parameter></parameter-list>"
+ + "<type line=\"2\">void</type><block line=\"2\"><var-list line=\"2\">"
+ + "<name-type-init line=\"2\"><name line=\"2\">a</name><vector line=\"2\">"
+ + "<type line=\"2\">String</type></vector><init line=\"2\"><new line=\"2\">"
+ + "<primary line=\"2\">Vector</primary><vector line=\"2\"><vector line=\"2\">"
+ + "<type line=\"2\">String</type></vector></vector><arguments line=\"2\">"
+ + "</arguments></new></init></name-type-init></var-list></block></function>" );
+ assertClassContent( "",
+ "private function foo(sf:int):void{"
+ + "var a:Vector.<String> = new Vector.<String>();}",
+ "<function line=\"2\"><mod-list line=\"2\"><mod line=\"2\">private</mod></mod-list>"
+ + "<name line=\"2\">foo</name><parameter-list line=\"2\"><parameter line=\"2\">"
+ + "<name-type-init line=\"2\"><name line=\"2\">sf</name><type line=\"2\">int</type>"
+ + "</name-type-init></parameter></parameter-list><type line=\"2\">void</type>"
+ + "<block line=\"2\"><var-list line=\"2\"><name-type-init line=\"2\">"
+ + "<name line=\"2\">a</name><vector line=\"2\"><type line=\"2\">String</type>"
+ + "</vector><init line=\"2\"><new line=\"2\"><primary line=\"2\">Vector</primary>"
+ + "<vector line=\"2\"><vector line=\"2\"><type line=\"2\">String</type></vector>"
+ + "</vector><arguments line=\"2\"></arguments></new></init></name-type-init>"
+ + "</var-list></block></function>" );
+ }
+
+ @Test
+ public void testImports() throws TokenException
+ {
+ assertClassContent( "1",
+ "import a.b.c;",
+ "<import line=\"2\">a.b.c</import>" );
+ assertClassContent( "2",
+ "import a.b.c import x.y.z",
+ "<import line=\"2\">a.b.c</import>"
+ + "<import line=\"2\">x.y.z</import>" );
+ }
+
+ @Test
+ public void testMethods() throws TokenException
+ {
+ assertClassContent( "1",
+ "function a(){}",
+ "<function line=\"2\"><mod-list line=\"2\">"
+ + "</mod-list><name line=\"2\">a</name><parameter-list line=\"2\""
+ + "></parameter-list><type line=\"2\"></type><block "
+ + "line=\"2\"></block></function>" );
+
+ assertClassContent( "2",
+ "function set a( value : int ) : void {}",
+ "<set line=\"2\"><mod-list line=\"2\">"
+ + "</mod-list><name line=\"2\">a</name>"
+ + "<parameter-list line=\"2\"><parameter line=\"2\">"
+ + "<name-type-init line=\"2\"><name line=\"2\">value"
+ + "</name><type line=\"2\">int</type></name-type-init></parameter>"
+ + "</parameter-list><type line=\"2\">void</type><block line=\"2\""
+ + "></block></set>" );
+
+ assertClassContent( "3",
+ "function get a() : int {}",
+ "<get line=\"2\"><mod-list line=\"2\">"
+ + "</mod-list><name line=\"2\">a</name><parameter-list line=\"2\""
+ + "></parameter-list><type line=\"2\">int"
+ + "</type><block line=\"2\"></block></get>" );
+
+ assertClassContent( "function with default parameter",
+ "public function newLine ( height:*='' ):void{}",
+ "<function line=\"2\"><mod-list line=\"2\"><mod line=\"2\""
+ + ">public</mod></mod-list><name line=\"2\">newLine"
+ + "</name><parameter-list line=\"2\"><parameter line=\"2\""
+ + "><name-type-init line=\"2\"><name line=\"2\""
+ + ">height</name><type line=\"2\">*</type>"
+ + "<init line=\"2\"><primary line=\"2\">''"
+ + "</primary></init></name-type-init></parameter></parameter-list>"
+ + "<type line=\"2\">void</type><block line=\"2\">" + "</block></function>" );
+ }
+
+ @Test
+ public void testMethodsWithAsDoc() throws TokenException
+ {
+ scn.setLines( new String[]
+ { "{",
+ "/** AsDoc */public function a(){}",
+ "}",
+ "__END__" } );
+ asp.nextToken(); // first call
+ asp.nextToken(); // skip {
+
+ assertEquals( "<content line=\"2\"><function line=\"2\">"
+ + "<as-doc line=\"2\">/** AsDoc */</as-doc><mod-list "
+ + "line=\"2\"><mod line=\"2\">public</mod>"
+ + "</mod-list><name line=\"2\">a</name><parameter-list "
+ + "line=\"2\"></parameter-list><type line=\"2\">"
+ + "</type><block line=\"2\"></block></function></content>",
+ new ASTToXMLConverter().convert( asp.parseClassContent() ) );
+ }
+
+ @Test
+ public void testMethodsWithMultiLineComments() throws TokenException
+ {
+ scn.setLines( new String[]
+ { "{",
+ "/* Commented */public function a(){}",
+ "}",
+ "__END__" } );
+ asp.nextToken(); // first call
+ asp.nextToken(); // skip {
+
+ assertEquals( "<content line=\"2\"><multi-line-comment line=\"2\">"
+ + "/* Commented */</multi-line-comment><function line=\"2\">"
+ + "<mod-list line=\"2\"><mod line=\"2\">public"
+ + "</mod></mod-list><name line=\"2\">a</name><parameter-list "
+ + "line=\"2\"></parameter-list><type line=\"2\">"
+ + "</type><block line=\"2\"></block></function></content>",
+ new ASTToXMLConverter().convert( asp.parseClassContent() ) );
+ }
+
+ @Test
+ public void testMethodWithMetadataComment() throws TokenException
+ {
+ scn.setLines( new String[]
+ { "{",
+ "/* Comment */ [Bindable] public function a () : void { }",
+ "}",
+ "__END__" } );
+ asp.nextToken(); // first call
+ asp.nextToken(); // skip {
+
+ assertEquals( "1",
+ "<content line=\"2\"><multi-line-comment line=\"2\">"
+ + "/* Comment */</multi-line-comment><function line=\"2\">"
+ + "<meta-list line=\"2\"><meta line=\"2\">Bindable"
+ + "</meta></meta-list><mod-list line=\"2\"><mod line=\"2\""
+ + ">public</mod></mod-list><name line=\"2\">a</name>"
+ + "<parameter-list line=\"2\"></parameter-list><type line=\"2\""
+ + ">void</type><block line=\"2\"></block></function>" + "</content>",
+ new ASTToXMLConverter().convert( asp.parseClassContent() ) );
+ }
+
+ @Test
+ public void testRestParameter() throws TokenException
+ {
+ assertClassContent( "",
+ "public function log(message:String, ... rest):void{}",
+ "<function line=\"2\"><mod-list line=\"2\">"
+ + "<mod line=\"2\">public</mod></mod-list><name line=\"2\">"
+ + "log</name><parameter-list line=\"2\">"
+ + "<parameter line=\"2\"><name-type-init line=\"2\">"
+ + "<name line=\"2\">message</name><type line=\"2\">String"
+ + "</type></name-type-init></parameter><parameter line=\"2\">"
+ + "<rest line=\"2\">rest</rest></parameter></parameter-list>"
+ + "<type line=\"2\">void</type><block line=\"2\">" + "</block></function>" );
+ }
+
+ @Test
+ public void testVarDeclarations() throws TokenException
+ {
+ assertClassContent( "1",
+ "var a",
+ "<var-list line=\"2\"><mod-list line=\"2\">"
+ + "</mod-list><name-type-init line=\"2\"><name line=\"2\">a"
+ + "</name><type line=\"3\"></type></name-type-init></var-list>" );
+
+ assertClassContent( "2",
+ "public var a;",
+ "<var-list line=\"2\"><mod-list line=\"2\">"
+ + "<mod line=\"2\">public</mod></mod-list><name-type-init line=\"2\""
+ + "><name line=\"2\">a</name><type line=\"2\""
+ + "></type></name-type-init></var-list>" );
+
+ assertClassContent( "3",
+ "public static var a : int = 0",
+ "<var-list line=\"2\"><mod-list line=\"2\">"
+ + "<mod line=\"2\">public</mod><mod line=\"2\">"
+ + "static</mod></mod-list><name-type-init line=\"2\">"
+ + "<name line=\"2\">a</name><type line=\"2\">int</type>"
+ + "<init line=\"2\"><primary line=\"2\">0</primary>"
+ + "</init></name-type-init></var-list>" );
+
+ assertClassContent( "4",
+ "[Bindable] var a",
+ "<var-list line=\"2\"><meta-list line=\"2\">"
+ + "<meta line=\"2\">Bindable</meta></meta-list>"
+ + "<mod-list line=\"2\"></mod-list>" + "<name-type-init line=\"2\">"
+ + "<name line=\"2\">a</name><type line=\"3\">"
+ + "</type></name-type-init></var-list>" );
+ }
+
+ private void assertClassContent( final String message,
+ final String input,
+ final String expected ) throws TokenException
+ {
+ scn.setLines( new String[]
+ { "{",
+ input,
+ "}",
+ "__END__" } );
+ asp.nextToken(); // first call
+ asp.nextToken(); // skip {
+ final String result = new ASTToXMLConverter().convert( asp.parseClassContent() );
+ assertEquals( message,
+ "<content line=\"2\">"
+ + expected + "</content>",
+ result );
+ }
+
+ private void assertClassContent( final String message,
+ final String[] input,
+ final String expected ) throws TokenException
+ {
+ scn.setLines( input );
+ asp.nextToken(); // first call
+ asp.nextToken(); // skip {
+ final String result = new ASTToXMLConverter().convert( asp.parseClassContent() );
+ assertEquals( message,
+ "<content line=\"2\">"
+ + expected + "</content>",
+ result );
+ }
+}