blob: 67288df2464efff96a3949d7ae19a270c6a969ee [file] [log] [blame]
/*******************************************************************************
* 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();
}
}