/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.formatter; import java.util.ArrayList; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ArrayReference; import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference; import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.BinaryExpression; import org.eclipse.jdt.internal.compiler.ast.CastExpression; import org.eclipse.jdt.internal.compiler.ast.CharLiteral; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; import org.eclipse.jdt.internal.compiler.ast.CombinedBinaryExpression; import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment; import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; import org.eclipse.jdt.internal.compiler.ast.DoubleLiteral; import org.eclipse.jdt.internal.compiler.ast.EqualExpression; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral; import org.eclipse.jdt.internal.compiler.ast.FalseLiteral; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.FloatLiteral; import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression; import org.eclipse.jdt.internal.compiler.ast.IntLiteral; import org.eclipse.jdt.internal.compiler.ast.LongLiteral; import org.eclipse.jdt.internal.compiler.ast.MessageSend; import org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation; import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.PostfixExpression; import org.eclipse.jdt.internal.compiler.ast.PrefixExpression; import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.SuperReference; import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TrueLiteral; import org.eclipse.jdt.internal.compiler.ast.UnaryExpression; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; class BinaryExpressionFragmentBuilder extends ASTVisitor { ArrayList fragmentsList; ArrayList operatorsList; private int realFragmentsSize; BinaryExpressionFragmentBuilder() { this.fragmentsList = new ArrayList(); this.operatorsList = new ArrayList(); this.realFragmentsSize = 0; } private final void addRealFragment(ASTNode node) { this.fragmentsList.add(node); this.realFragmentsSize++; } private final void addSmallFragment(ASTNode node) { this.fragmentsList.add(node); } private boolean buildFragments(Expression expression) { if (((expression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) { addRealFragment(expression); return false; } return true; } public ASTNode[] fragments() { ASTNode[] fragments = new ASTNode[this.fragmentsList.size()]; this.fragmentsList.toArray(fragments); return fragments; } public int[] operators() { int length = this.operatorsList.size(); int[] tab = new int[length]; for (int i = 0; i < length; i++) { tab[i] = ((Integer)this.operatorsList.get(i)).intValue(); } return tab; } public int realFragmentsSize() { return this.realFragmentsSize; } public boolean visit( AllocationExpression allocationExpression, BlockScope scope) { addRealFragment(allocationExpression); return false; } public boolean visit( AND_AND_Expression and_and_Expression, BlockScope scope) { if (((and_and_Expression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) { addRealFragment(and_and_Expression); } else { and_and_Expression.left.traverse(this, scope); this.operatorsList.add(new Integer(TerminalTokens.TokenNameAND_AND)); and_and_Expression.right.traverse(this, scope); } return false; } public boolean visit( ArrayAllocationExpression arrayAllocationExpression, BlockScope scope) { addRealFragment(arrayAllocationExpression); return false; } public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) { addRealFragment(arrayInitializer); return false; } public boolean visit( ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope) { addRealFragment(arrayQualifiedTypeReference); return false; } public boolean visit( ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope) { addRealFragment(arrayQualifiedTypeReference); return false; } public boolean visit(ArrayReference arrayReference, BlockScope scope) { addRealFragment(arrayReference); return false; } public boolean visit( ArrayTypeReference arrayTypeReference, BlockScope scope) { addRealFragment(arrayTypeReference); return false; } public boolean visit( ArrayTypeReference arrayTypeReference, ClassScope scope) { addRealFragment(arrayTypeReference); return false; } public boolean visit(Assignment assignment, BlockScope scope) { addRealFragment(assignment); return false; } public boolean visit(BinaryExpression binaryExpression, BlockScope scope) { if (binaryExpression instanceof CombinedBinaryExpression) { CombinedBinaryExpression expression = (CombinedBinaryExpression) binaryExpression; if (expression.referencesTable != null) { return this.visit(expression, scope); } } final int numberOfParens = (binaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT; if (numberOfParens > 0) { addRealFragment(binaryExpression); } else { switch((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) { case OperatorIds.PLUS : if (buildFragments(binaryExpression)) { binaryExpression.left.traverse(this, scope); this.operatorsList.add(new Integer(TerminalTokens.TokenNamePLUS)); binaryExpression.right.traverse(this, scope); } return false; case OperatorIds.MINUS : if (buildFragments(binaryExpression)) { binaryExpression.left.traverse(this, scope); this.operatorsList.add(new Integer(TerminalTokens.TokenNameMINUS)); binaryExpression.right.traverse(this, scope); } return false; case OperatorIds.MULTIPLY : if (buildFragments(binaryExpression)) { binaryExpression.left.traverse(this, scope); this.operatorsList.add(new Integer(TerminalTokens.TokenNameMULTIPLY)); binaryExpression.right.traverse(this, scope); } return false; case OperatorIds.REMAINDER : if (buildFragments(binaryExpression)) { binaryExpression.left.traverse(this, scope); this.operatorsList.add(new Integer(TerminalTokens.TokenNameREMAINDER)); binaryExpression.right.traverse(this, scope); } return false; case OperatorIds.XOR : if (buildFragments(binaryExpression)) { binaryExpression.left.traverse(this, scope); this.operatorsList.add(new Integer(TerminalTokens.TokenNameXOR)); binaryExpression.right.traverse(this, scope); } return false; case OperatorIds.DIVIDE : if (buildFragments(binaryExpression)) { binaryExpression.left.traverse(this, scope); this.operatorsList.add(new Integer(TerminalTokens.TokenNameDIVIDE)); binaryExpression.right.traverse(this, scope); } return false; case OperatorIds.OR : if (buildFragments(binaryExpression)) { binaryExpression.left.traverse(this, scope); this.operatorsList.add(new Integer(TerminalTokens.TokenNameOR)); binaryExpression.right.traverse(this, scope); } return false; case OperatorIds.AND : if (buildFragments(binaryExpression)) { binaryExpression.left.traverse(this, scope); this.operatorsList.add(new Integer(TerminalTokens.TokenNameAND)); binaryExpression.right.traverse(this, scope); } return false; default: addRealFragment(binaryExpression); } } return false; } public boolean visit(CombinedBinaryExpression combinedBinaryExpression, BlockScope scope) { // keep implementation in sync with BinaryExpression#resolveType if (combinedBinaryExpression.referencesTable == null) { addRealFragment(combinedBinaryExpression.left); this.operatorsList.add(new Integer(TerminalTokens.TokenNamePLUS)); addRealFragment(combinedBinaryExpression.right); return false; } BinaryExpression cursor = combinedBinaryExpression.referencesTable[0]; if (cursor.left instanceof CombinedBinaryExpression) { this.visit((CombinedBinaryExpression) cursor.left, scope); } else { addRealFragment(cursor.left); } for (int i = 0, end = combinedBinaryExpression.arity; i < end; i ++) { this.operatorsList.add(new Integer(TerminalTokens.TokenNamePLUS)); addRealFragment(combinedBinaryExpression.referencesTable[i].right); } this.operatorsList.add(new Integer(TerminalTokens.TokenNamePLUS)); addRealFragment(combinedBinaryExpression.right); return false; } public boolean visit(CastExpression castExpression, BlockScope scope) { addRealFragment(castExpression); return false; } public boolean visit(CharLiteral charLiteral, BlockScope scope) { addSmallFragment(charLiteral); return false; } public boolean visit( ClassLiteralAccess classLiteralAccess, BlockScope scope) { addRealFragment(classLiteralAccess); return false; } public boolean visit( CompoundAssignment compoundAssignment, BlockScope scope) { addRealFragment(compoundAssignment); return false; } public boolean visit( ConditionalExpression conditionalExpression, BlockScope scope) { addRealFragment(conditionalExpression); return false; } public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) { addSmallFragment(doubleLiteral); return false; } public boolean visit(EqualExpression equalExpression, BlockScope scope) { addRealFragment(equalExpression); return false; } public boolean visit( ExtendedStringLiteral extendedStringLiteral, BlockScope scope) { addRealFragment(extendedStringLiteral); return false; } public boolean visit(FalseLiteral falseLiteral, BlockScope scope) { addSmallFragment(falseLiteral); return false; } public boolean visit(FieldReference fieldReference, BlockScope scope) { addRealFragment(fieldReference); return false; } public boolean visit(FloatLiteral floatLiteral, BlockScope scope) { addSmallFragment(floatLiteral); return false; } public boolean visit( InstanceOfExpression instanceOfExpression, BlockScope scope) { addRealFragment(instanceOfExpression); return false; } public boolean visit(IntLiteral intLiteral, BlockScope scope) { addSmallFragment(intLiteral); return false; } public boolean visit(LongLiteral longLiteral, BlockScope scope) { addSmallFragment(longLiteral); return false; } public boolean visit(MessageSend messageSend, BlockScope scope) { addRealFragment(messageSend); return false; } public boolean visit(StringLiteralConcatenation stringLiteral, BlockScope scope) { if (((stringLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) { addRealFragment(stringLiteral); } else { for (int i = 0, max = stringLiteral.counter; i < max; i++) { addRealFragment(stringLiteral.literals[i]); if (i < max - 1) { this.operatorsList.add(new Integer(TerminalTokens.TokenNamePLUS)); } } } return false; } public boolean visit(NullLiteral nullLiteral, BlockScope scope) { addRealFragment(nullLiteral); return false; } public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) { if (((or_or_Expression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) { addRealFragment(or_or_Expression); } else { or_or_Expression.left.traverse(this, scope); this.operatorsList.add(new Integer(TerminalTokens.TokenNameOR_OR)); or_or_Expression.right.traverse(this, scope); } return false; } public boolean visit( PostfixExpression postfixExpression, BlockScope scope) { addRealFragment(postfixExpression); return false; } public boolean visit(PrefixExpression prefixExpression, BlockScope scope) { addRealFragment(prefixExpression); return false; } public boolean visit( QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope) { addRealFragment(qualifiedAllocationExpression); return false; } public boolean visit( QualifiedNameReference qualifiedNameReference, BlockScope scope) { addRealFragment(qualifiedNameReference); return false; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public boolean visit( QualifiedSuperReference qualifiedSuperReference, BlockScope scope) { addRealFragment(qualifiedSuperReference); return false; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public boolean visit( QualifiedThisReference qualifiedThisReference, BlockScope scope) { addRealFragment(qualifiedThisReference); return false; } public boolean visit( SingleNameReference singleNameReference, BlockScope scope) { addRealFragment(singleNameReference); return false; } public boolean visit(StringLiteral stringLiteral, BlockScope scope) { addRealFragment(stringLiteral); return false; } /* (non-Javadoc) * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SuperReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope) */ public boolean visit(SuperReference superReference, BlockScope scope) { addRealFragment(superReference); return false; } public boolean visit(ThisReference thisReference, BlockScope scope) { addRealFragment(thisReference); return false; } public boolean visit(TrueLiteral trueLiteral, BlockScope scope) { addSmallFragment(trueLiteral); return false; } public boolean visit(UnaryExpression unaryExpression, BlockScope scope) { addRealFragment(unaryExpression); return false; } public int size() { return this.fragmentsList.size(); } }