View | Details | Raw Unified | Return to bug 49412 | Differences between
and this patch

Collapse All | Expand All

(-)formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java (+68 lines)
Lines 572-582 Link Here
572
	 * @see #TRUE
572
	 * @see #TRUE
573
	 * @see #FALSE
573
	 * @see #FALSE
574
	 * @since 3.1
574
	 * @since 3.1
575
	 * @deprecated Use {@link #FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_BLOCK_COMMENT} and {@link #FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_JAVADOC_COMMENT}
575
	 */	
576
	 */	
576
	public final static String FORMATTER_COMMENT_CLEAR_BLANK_LINES = "org.eclipse.jdt.core.formatter.comment.clear_blank_lines"; //$NON-NLS-1$
577
	public final static String FORMATTER_COMMENT_CLEAR_BLANK_LINES = "org.eclipse.jdt.core.formatter.comment.clear_blank_lines"; //$NON-NLS-1$
577
	
578
	
578
	/**
579
	/**
579
	 * <pre>
580
	 * <pre>
581
	 * FORMATTER / Option to control whether blank lines are cleared inside javadoc comments
582
	 *     - option id:         "org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment"
583
	 *     - possible values:   { TRUE, FALSE }
584
	 *     - default:           FALSE
585
	 * </pre>
586
	 * @see #TRUE
587
	 * @see #FALSE
588
	 * @since 3.3
589
	 */	
590
	public final static String FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_JAVADOC_COMMENT = "org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment"; //$NON-NLS-1$
591
592
	/**
593
	 * <pre>
594
	 * FORMATTER / Option to control whether blank lines are cleared inside block comments
595
	 *     - option id:         "org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment"
596
	 *     - possible values:   { TRUE, FALSE }
597
	 *     - default:           FALSE
598
	 * </pre>
599
	 * @see #TRUE
600
	 * @see #FALSE
601
	 * @since 3.3
602
	 */	
603
	public final static String FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_BLOCK_COMMENT = "org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment"; //$NON-NLS-1$
604
605
	/**
606
	 * <pre>
580
	 * FORMATTER / Option to control whether comments are formatted
607
	 * FORMATTER / Option to control whether comments are formatted
581
	 *     - option id:         "org.eclipse.jdt.core.formatter.comment.format_comments"
608
	 *     - option id:         "org.eclipse.jdt.core.formatter.comment.format_comments"
582
	 *     - possible values:   { TRUE, FALSE }
609
	 *     - possible values:   { TRUE, FALSE }
Lines 585-595 Link Here
585
	 * @see #TRUE
612
	 * @see #TRUE
586
	 * @see #FALSE
613
	 * @see #FALSE
587
	 * @since 3.1
614
	 * @since 3.1
615
	 * @deprecated Use multiple settings for each kind of comments. See {@link #FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT},
616
	 * {@link #FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT} and {@link #FORMATTER_COMMENT_FORMAT_LINE_COMMENT}.
588
	 */	
617
	 */	
589
	public final static String FORMATTER_COMMENT_FORMAT = "org.eclipse.jdt.core.formatter.comment.format_comments"; //$NON-NLS-1$
618
	public final static String FORMATTER_COMMENT_FORMAT = "org.eclipse.jdt.core.formatter.comment.format_comments"; //$NON-NLS-1$
590
619
591
	/**
620
	/**
592
	 * <pre>
621
	 * <pre>
622
	 * FORMATTER / Option to control whether single line comments are formatted
623
	 *     - option id:         "org.eclipse.jdt.core.formatter.comment.format_line_comments"
624
	 *     - possible values:   { TRUE, FALSE }
625
	 *     - default:           TRUE
626
	 * </pre>
627
	 * @see #TRUE
628
	 * @see #FALSE
629
	 * @since 3.3
630
	 */	
631
	public final static String FORMATTER_COMMENT_FORMAT_LINE_COMMENT = "org.eclipse.jdt.core.formatter.comment.format_line_comments"; //$NON-NLS-1$
632
633
	/**
634
	 * <pre>
635
	 * FORMATTER / Option to control whether multiple comments are formatted
636
	 *     - option id:         "org.eclipse.jdt.core.formatter.comment.format_block_comments"
637
	 *     - possible values:   { TRUE, FALSE }
638
	 *     - default:           TRUE
639
	 * </pre>
640
	 * @see #TRUE
641
	 * @see #FALSE
642
	 * @since 3.3
643
	 */	
644
	public final static String FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT = "org.eclipse.jdt.core.formatter.comment.format_block_comments"; //$NON-NLS-1$
645
646
	/**
647
	 * <pre>
648
	 * FORMATTER / Option to control whether javadoc comments are formatted
649
	 *     - option id:         "org.eclipse.jdt.core.formatter.comment.format_javadoc_comments"
650
	 *     - possible values:   { TRUE, FALSE }
651
	 *     - default:           TRUE
652
	 * </pre>
653
	 * @see #TRUE
654
	 * @see #FALSE
655
	 * @since 3.3
656
	 */	
657
	public final static String FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT = "org.eclipse.jdt.core.formatter.comment.format_javadoc_comments"; //$NON-NLS-1$
658
659
	/**
660
	 * <pre>
593
	 * FORMATTER / Option to control whether the header comment of a Java source file is formatted
661
	 * FORMATTER / Option to control whether the header comment of a Java source file is formatted
594
	 *     - option id:         "org.eclipse.jdt.core.formatter.comment.format_header"
662
	 *     - option id:         "org.eclipse.jdt.core.formatter.comment.format_header"
595
	 *     - possible values:   { TRUE, FALSE }
663
	 *     - possible values:   { TRUE, FALSE }
(-)formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor2.java (-3403 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2002, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.formatter;
12
13
import java.util.List;
14
import java.util.Map;
15
16
import org.eclipse.jdt.core.JavaCore;
17
import org.eclipse.jdt.core.compiler.InvalidInputException;
18
import org.eclipse.jdt.core.dom.*;
19
import org.eclipse.jdt.core.dom.PrefixExpression.Operator;
20
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
21
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
22
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
23
import org.eclipse.jdt.internal.compiler.parser.Scanner;
24
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
25
import org.eclipse.jdt.internal.formatter.align.Alignment;
26
import org.eclipse.jdt.internal.formatter.align.Alignment2;
27
import org.eclipse.jdt.internal.formatter.align.AlignmentException;
28
import org.eclipse.text.edits.TextEdit;
29
30
/**
31
 * This class is responsible for formatting a valid java source code.
32
 * @since 3.2
33
 */
34
public class CodeFormatterVisitor2 extends ASTVisitor {
35
	public final static boolean DEBUG = false;
36
	
37
	private static final int[] CLOSING_GENERICS_EXPECTEDTOKENS = new int[] {
38
		TerminalTokens.TokenNameRIGHT_SHIFT,
39
		TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT,
40
		TerminalTokens.TokenNameGREATER
41
	};
42
	private static final int[] NUMBER_LITERALS_EXPECTEDTOKENS = new int[] {
43
		TerminalTokens.TokenNameIntegerLiteral,
44
		TerminalTokens.TokenNameLongLiteral,
45
		TerminalTokens.TokenNameFloatingPointLiteral,
46
		TerminalTokens.TokenNameDoubleLiteral
47
	};
48
	/*
49
	 * Set of expected tokens type for a single type reference.
50
	 * This array needs to be SORTED.
51
	 */
52
	private static final int[] PRIMITIVE_TYPE_EXPECTEDTOKENS = new int[] {
53
		TerminalTokens.TokenNameboolean,
54
		TerminalTokens.TokenNamebyte,
55
		TerminalTokens.TokenNamechar,
56
		TerminalTokens.TokenNamedouble,
57
		TerminalTokens.TokenNamefloat,
58
		TerminalTokens.TokenNameint,
59
		TerminalTokens.TokenNamelong,
60
		TerminalTokens.TokenNameshort,
61
		TerminalTokens.TokenNamevoid
62
	};
63
	private Scanner localScanner;
64
65
	public DefaultCodeFormatterOptions preferences;
66
	
67
	public Scribe2 scribe;
68
69
	public CodeFormatterVisitor2(DefaultCodeFormatterOptions preferences, Map settings, int offset, int length, CompilationUnit unit) {
70
		long sourceLevel = settings == null
71
			? ClassFileConstants.JDK1_3
72
			: CompilerOptions.versionToJdkLevel(settings.get(JavaCore.COMPILER_SOURCE));
73
		this.localScanner = new Scanner(true, false, false/*nls*/, sourceLevel/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
74
		
75
		this.preferences = preferences;
76
		this.scribe = new Scribe2(this, sourceLevel, offset, length, unit);
77
	}
78
79
	private boolean commentStartsBlock(int start, int end) {
80
		this.localScanner.resetTo(start, end);
81
		try {
82
			if (this.localScanner.getNextToken() ==  TerminalTokens.TokenNameLBRACE) {
83
				switch(this.localScanner.getNextToken()) {
84
					case TerminalTokens.TokenNameCOMMENT_BLOCK :
85
					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
86
					case TerminalTokens.TokenNameCOMMENT_LINE :
87
						return true;
88
				}
89
			}
90
		} catch(InvalidInputException e) {
91
			// ignore
92
		}
93
		return false;
94
	}
95
	
96
97
	public static int extractInfixExpressionOperator(InfixExpression node) {
98
		final InfixExpression.Operator infixOperator = node.getOperator();
99
		if (infixOperator == InfixExpression.Operator.AND) {
100
			return TerminalTokens.TokenNameAND;
101
		} else if (infixOperator == InfixExpression.Operator.CONDITIONAL_AND) {
102
			return TerminalTokens.TokenNameAND_AND;
103
		} else if (infixOperator == InfixExpression.Operator.CONDITIONAL_OR) {
104
			return TerminalTokens.TokenNameOR_OR;
105
		} else if (infixOperator == InfixExpression.Operator.DIVIDE) {
106
			return TerminalTokens.TokenNameDIVIDE;
107
		} else if (infixOperator == InfixExpression.Operator.EQUALS) {
108
			return TerminalTokens.TokenNameEQUAL_EQUAL;
109
		} else if (infixOperator == InfixExpression.Operator.GREATER) {
110
			return TerminalTokens.TokenNameGREATER;
111
		} else if (infixOperator == InfixExpression.Operator.GREATER_EQUALS) {
112
			return TerminalTokens.TokenNameGREATER_EQUAL;
113
		} else if (infixOperator == InfixExpression.Operator.LEFT_SHIFT) {
114
			return TerminalTokens.TokenNameLEFT_SHIFT;
115
		} else if (infixOperator == InfixExpression.Operator.LESS) {
116
			return TerminalTokens.TokenNameLESS;
117
		} else if (infixOperator == InfixExpression.Operator.LESS_EQUALS) {
118
			return TerminalTokens.TokenNameLESS_EQUAL;
119
		} else if (infixOperator == InfixExpression.Operator.MINUS) {
120
			return TerminalTokens.TokenNameMINUS;
121
		} else if (infixOperator == InfixExpression.Operator.NOT_EQUALS) {
122
			return TerminalTokens.TokenNameNOT_EQUAL;
123
		} else if (infixOperator == InfixExpression.Operator.OR) {
124
			return TerminalTokens.TokenNameOR;
125
		} else if (infixOperator == InfixExpression.Operator.PLUS) {
126
			return TerminalTokens.TokenNamePLUS;
127
		} else if (infixOperator == InfixExpression.Operator.REMAINDER) {
128
			return TerminalTokens.TokenNameREMAINDER;
129
		} else if (infixOperator == InfixExpression.Operator.RIGHT_SHIFT_SIGNED) {
130
			return TerminalTokens.TokenNameRIGHT_SHIFT;
131
		} else if (infixOperator == InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED) {
132
			return TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT;
133
		} else if (infixOperator == InfixExpression.Operator.TIMES) {
134
			return TerminalTokens.TokenNameMULTIPLY;
135
		} else {
136
			return TerminalTokens.TokenNameXOR;
137
		}
138
	}
139
140
	private final TextEdit failedToFormat() {
141
		if (DEBUG) {
142
			System.out.println("COULD NOT FORMAT \n" + this.scribe.scanner); //$NON-NLS-1$
143
			System.out.println(this.scribe);
144
		}
145
		return null;
146
	}
147
148
	/**
149
	 * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
150
	 */
151
	public TextEdit format(String string, AbstractTypeDeclaration typeDeclaration) {
152
		// reset the scribe
153
		this.scribe.reset();
154
		
155
		long startTime = System.currentTimeMillis();
156
	
157
		final char[] compilationUnitSource = string.toCharArray();
158
		
159
		this.localScanner.setSource(compilationUnitSource);
160
		this.scribe.initializeScanner(compilationUnitSource);
161
	
162
		try {
163
			this.scribe.lastNumberOfNewLines = 1;
164
			formatTypeMembers(typeDeclaration.bodyDeclarations(), false);
165
		} catch(AbortFormatting e){
166
			return failedToFormat();
167
		}
168
		if (DEBUG){
169
			System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime));  //$NON-NLS-1$
170
		}
171
		return this.scribe.getRootEdit();
172
	}
173
174
	/**
175
	 * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
176
	 */
177
	public TextEdit format(String string, Block block) {
178
		// reset the scribe
179
		this.scribe.reset();
180
		
181
		long startTime = System.currentTimeMillis();
182
183
		final char[] compilationUnitSource = string.toCharArray();
184
		
185
		this.localScanner.setSource(compilationUnitSource);
186
		this.scribe.initializeScanner(compilationUnitSource);
187
188
		if ((block.getFlags() & ASTNode.MALFORMED) != 0) {
189
			return failedToFormat();
190
		}
191
192
		try {
193
			formatStatements(block.statements(), false);
194
			if (hasComments()) {
195
				this.scribe.printNewLine();
196
			}
197
			this.scribe.printComment();
198
		} catch(AbortFormatting e){
199
			return failedToFormat();
200
		}
201
		if (DEBUG){
202
			System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime));  //$NON-NLS-1$
203
		}
204
		return this.scribe.getRootEdit();
205
	}
206
207
	/**
208
	 * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
209
	 */
210
	public TextEdit format(String string, CompilationUnit compilationUnit) {
211
		// reset the scribe
212
		this.scribe.reset();
213
		
214
		if ((compilationUnit.getFlags() & ASTNode.MALFORMED) != 0) {
215
			return failedToFormat();
216
		}
217
218
		long startTime = System.currentTimeMillis();
219
220
		final char[] compilationUnitSource = string.toCharArray();
221
		
222
		this.localScanner.setSource(compilationUnitSource);
223
		this.scribe.initializeScanner(compilationUnitSource);
224
225
		try {
226
			compilationUnit.accept(this);
227
		} catch(AbortFormatting e){
228
			return failedToFormat();
229
		}
230
		if (DEBUG){
231
			System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime));  //$NON-NLS-1$
232
		}
233
		return this.scribe.getRootEdit();
234
	}
235
236
	/**
237
	 * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
238
	 */
239
	public TextEdit format(String string, Expression expression) {
240
		// reset the scribe
241
		this.scribe.reset();
242
		
243
		long startTime = System.currentTimeMillis();
244
245
		final char[] compilationUnitSource = string.toCharArray();
246
		
247
		this.localScanner.setSource(compilationUnitSource);
248
		this.scribe.initializeScanner(compilationUnitSource);
249
250
		if ((expression.getFlags() & ASTNode.MALFORMED) != 0) {
251
			return failedToFormat();
252
		}
253
		try {
254
			expression.accept(this);
255
			this.scribe.printComment();
256
		} catch(AbortFormatting e){
257
			return failedToFormat();
258
		}
259
		if (DEBUG){
260
			System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime));  //$NON-NLS-1$
261
		}
262
		return this.scribe.getRootEdit();
263
	}
264
265
    private void format(
266
			AbstractTypeDeclaration memberTypeDeclaration,
267
			boolean isChunkStart,
268
			boolean isFirstClassBodyDeclaration) {
269
270
			if (isFirstClassBodyDeclaration) {
271
				int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
272
				if (newLinesBeforeFirstClassBodyDeclaration > 0) {
273
					this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
274
				}
275
			} else {
276
				int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
277
				if (newLineBeforeChunk > 0) {
278
					this.scribe.printEmptyLines(newLineBeforeChunk);
279
				}
280
				final int newLinesBeforeMember = this.preferences.blank_lines_before_member_type;
281
				if (newLinesBeforeMember > 0) {
282
					this.scribe.printEmptyLines(newLinesBeforeMember);
283
				}
284
			}
285
			memberTypeDeclaration.accept(this);
286
		}
287
288
	private void format(FieldDeclaration fieldDeclaration, boolean isChunkStart, boolean isFirstClassBodyDeclaration) {
289
		if (isFirstClassBodyDeclaration) {
290
			int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
291
			if (newLinesBeforeFirstClassBodyDeclaration > 0) {
292
				this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
293
			}
294
		} else {
295
			int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
296
			if (newLineBeforeChunk > 0) {
297
				this.scribe.printEmptyLines(newLineBeforeChunk);
298
			}
299
			final int newLinesBeforeField = this.preferences.blank_lines_before_field;
300
			if (newLinesBeforeField > 0) {
301
				this.scribe.printEmptyLines(newLinesBeforeField);
302
			}
303
		}
304
		Alignment2 memberAlignment = this.scribe.getMemberAlignment();
305
	
306
        this.scribe.printComment();
307
		final List modifiers = fieldDeclaration.modifiers();
308
		if (modifiers.size() != 0) {
309
			this.scribe.printModifiers(modifiers, this);
310
			this.scribe.space();
311
		}
312
313
		fieldDeclaration.getType().accept(this);
314
		
315
		List fragments = fieldDeclaration.fragments();
316
		final int fragmentsLength = fragments.size();
317
		if (fragmentsLength > 1) {
318
			// multiple field declaration
319
			Alignment2 multiFieldDeclarationsAlignment =this.scribe.createAlignment(
320
					"multiple_field",//$NON-NLS-1$
321
					this.preferences.alignment_for_multiple_fields,
322
					fragmentsLength - 1,
323
					this.scribe.scanner.currentPosition);
324
			this.scribe.enterAlignment(multiFieldDeclarationsAlignment);
325
		
326
			boolean ok = false;
327
			do {
328
				try {
329
					for (int i = 0; i < fragmentsLength; i++) {
330
						VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(i);
331
						/*
332
						 * Field name
333
						 */
334
						if (i == 0) {
335
							this.scribe.alignFragment(memberAlignment, 0);
336
							this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
337
						} else {
338
							this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
339
						}
340
				
341
						/*
342
						 * Check for extra dimensions
343
						 */
344
						final int extraDimensions = fragment.getExtraDimensions();
345
						if (extraDimensions != 0) {
346
							 for (int index = 0; index < extraDimensions; index++) {
347
							 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
348
							 	this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
349
							 }
350
						}
351
					
352
						/*
353
						 * Field initialization
354
						 */
355
						final Expression initialization = fragment.getInitializer();
356
						if (initialization != null) {
357
							if (i == 0) {
358
								this.scribe.alignFragment(memberAlignment, 1);
359
							}
360
							this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
361
							if (this.preferences.insert_space_after_assignment_operator) {
362
								this.scribe.space();
363
							}
364
							Alignment2 assignmentAlignment = this.scribe.createAlignment("fieldDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
365
							this.scribe.enterAlignment(assignmentAlignment);
366
							boolean ok2 = false;
367
							do {
368
								try {
369
									this.scribe.alignFragment(assignmentAlignment, 0);
370
									initialization.accept(this);
371
									ok2 = true;
372
								} catch(AlignmentException e){
373
									this.scribe.redoAlignment(e);
374
								}
375
							} while (!ok2);		
376
							this.scribe.exitAlignment(assignmentAlignment, true);			
377
						}
378
						
379
						if (i != fragmentsLength - 1) {
380
							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_multiple_field_declarations);
381
							this.scribe.printTrailingComment();
382
							this.scribe.alignFragment(multiFieldDeclarationsAlignment, i);
383
384
							if (this.preferences.insert_space_after_comma_in_multiple_field_declarations) {
385
								this.scribe.space();
386
							}
387
						} else {
388
							this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
389
							this.scribe.alignFragment(memberAlignment, 2);
390
							this.scribe.printTrailingComment();
391
						}
392
					}
393
					ok = true;
394
				} catch (AlignmentException e) {
395
					this.scribe.redoAlignment(e);
396
				}
397
			} while (!ok);
398
			this.scribe.exitAlignment(multiFieldDeclarationsAlignment, true);				
399
		} else {
400
			// single field declaration
401
			this.scribe.alignFragment(memberAlignment, 0);
402
			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
403
			VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
404
			final int extraDimensions = fragment.getExtraDimensions();
405
			if (extraDimensions != 0) {
406
				for (int i = 0; i < extraDimensions; i++) {
407
					this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
408
					this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
409
				}
410
			}
411
			final Expression initialization = fragment.getInitializer();
412
			if (initialization != null) {
413
				this.scribe.alignFragment(memberAlignment, 1);
414
				this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
415
				if (this.preferences.insert_space_after_assignment_operator) {
416
					this.scribe.space();
417
				}
418
				Alignment2 assignmentAlignment = this.scribe.createAlignment("fieldDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
419
				this.scribe.enterAlignment(assignmentAlignment);
420
				boolean ok = false;
421
				do {
422
					try {
423
						this.scribe.alignFragment(assignmentAlignment, 0);
424
						initialization.accept(this);
425
						ok = true;
426
					} catch(AlignmentException e){
427
						this.scribe.redoAlignment(e);
428
					}
429
				} while (!ok);		
430
				this.scribe.exitAlignment(assignmentAlignment, true);			
431
			}
432
			
433
			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
434
435
			if (memberAlignment != null) {
436
				this.scribe.alignFragment(memberAlignment, 2);
437
				this.scribe.printTrailingComment();
438
			} else {
439
				this.scribe.space();
440
				this.scribe.printTrailingComment();
441
			}
442
		}
443
	}
444
	private void format(
445
			BodyDeclaration bodyDeclaration,
446
			boolean isChunkStart,
447
			boolean isFirstClassBodyDeclaration) {
448
449
		if (isFirstClassBodyDeclaration) {
450
			int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
451
			if (newLinesBeforeFirstClassBodyDeclaration > 0) {
452
				this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
453
			}
454
		} else {
455
			final int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
456
			if (newLineBeforeChunk > 0) {
457
				this.scribe.printEmptyLines(newLineBeforeChunk);
458
			}
459
		}
460
		final int newLinesBeforeMethod = this.preferences.blank_lines_before_method;
461
		if (newLinesBeforeMethod > 0 && !isFirstClassBodyDeclaration) {
462
			this.scribe.printEmptyLines(newLinesBeforeMethod);
463
		} else if (this.scribe.line != 0 || this.scribe.column != 1) {
464
			this.scribe.printNewLine();
465
		}
466
		bodyDeclaration.accept(this);
467
	}
468
469
	private void formatAction(final int line, final Statement action, boolean insertLineForSingleStatement) {
470
		if (action != null) {
471
			switch(action.getNodeType()) {
472
				case ASTNode.BLOCK :
473
	                formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
474
					action.accept(this);
475
					break;
476
				case ASTNode.EMPTY_STATEMENT :
477
					this.scribe.indent();
478
					action.accept(this);
479
					this.scribe.unIndent();
480
					break;
481
				default :
482
					this.scribe.printNewLine();
483
					this.scribe.indent();
484
					action.accept(this);
485
					this.scribe.unIndent();
486
					if (insertLineForSingleStatement) {
487
						this.scribe.printNewLine();
488
					}
489
			}
490
		}
491
	}
492
493
	private void formatBlock(Block block, String block_brace_position, boolean insertSpaceBeforeOpeningBrace) {
494
		formatOpeningBrace(block_brace_position, insertSpaceBeforeOpeningBrace);
495
		final List statements = block.statements();
496
		final int statementsLength = statements.size();
497
		if (statementsLength != 0) {
498
			this.scribe.printNewLine();
499
			if (this.preferences.indent_statements_compare_to_block) {
500
				this.scribe.indent();
501
			}
502
			formatStatements(statements, true);
503
			this.scribe.printComment();
504
	
505
			if (this.preferences.indent_statements_compare_to_block) {
506
				this.scribe.unIndent();
507
			}
508
		} else {
509
			if (this.preferences.insert_new_line_in_empty_block) {
510
				this.scribe.printNewLine();
511
			}
512
			if (this.preferences.indent_statements_compare_to_block) {
513
				this.scribe.indent();
514
			}
515
			this.scribe.printComment();
516
	
517
			if (this.preferences.indent_statements_compare_to_block) {
518
				this.scribe.unIndent();
519
			}
520
		}
521
		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
522
		this.scribe.printTrailingComment();
523
		if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(block_brace_position)) {
524
			this.scribe.unIndent();
525
		}
526
	}
527
528
	private void formatEmptyTypeDeclaration(boolean isFirst) {
529
		boolean hasSemiColon = isNextToken(TerminalTokens.TokenNameSEMICOLON);
530
		while(isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
531
			this.scribe.printComment();
532
			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
533
			this.scribe.printTrailingComment();
534
		}
535
		if (hasSemiColon && isFirst) {
536
			this.scribe.printNewLine();
537
		}
538
	}
539
540
541
	private void formatLeftCurlyBrace(final int line, final String bracePosition) {
542
        /*
543
         * deal with (quite unexpected) comments right before lcurly
544
         */
545
        this.scribe.printComment();
546
        if (DefaultCodeFormatterConstants.NEXT_LINE_ON_WRAP.equals(bracePosition)
547
                && (this.scribe.line > line || this.scribe.column >= this.preferences.page_width)) 
548
        {
549
            this.scribe.printNewLine();
550
        }
551
    }
552
553
	private void formatLocalDeclaration(VariableDeclarationExpression declarationExpression, boolean insertSpaceBeforeComma, boolean insertSpaceAfterComma) {
554
		final List modifiers = declarationExpression.modifiers();
555
		if (modifiers.size() != 0) {
556
			this.scribe.printModifiers(modifiers, this);
557
			this.scribe.space();
558
		}
559
560
		declarationExpression.getType().accept(this);
561
		
562
		formatVariableDeclarationFragments(declarationExpression.fragments(), insertSpaceBeforeComma, insertSpaceAfterComma);
563
	}
564
565
	private void formatVariableDeclarationFragments(final List fragments, boolean insertSpaceBeforeComma, boolean insertSpaceAfterComma) {
566
		final int fragmentsLength = fragments.size();
567
		if (fragmentsLength > 1) {
568
			// multiple field declaration
569
			Alignment2 multiFieldDeclarationsAlignment =this.scribe.createAlignment(
570
					"multiple_field",//$NON-NLS-1$
571
					this.preferences.alignment_for_multiple_fields,
572
					fragmentsLength - 1,
573
					this.scribe.scanner.currentPosition);
574
			this.scribe.enterAlignment(multiFieldDeclarationsAlignment);
575
		
576
			boolean ok = false;
577
			do {
578
				try {
579
					for (int i = 0; i < fragmentsLength; i++) {
580
						VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(i);
581
						/*
582
						 * Field name
583
						 */
584
						if (i == 0) {
585
							this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
586
						} else {
587
							this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
588
						}
589
				
590
						/*
591
						 * Check for extra dimensions
592
						 */
593
						final int extraDimensions = fragment.getExtraDimensions();
594
						if (extraDimensions != 0) {
595
							 for (int index = 0; index < extraDimensions; index++) {
596
							 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
597
							 	this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
598
							 }
599
						}
600
					
601
						/*
602
						 * Field initialization
603
						 */
604
						final Expression initialization = fragment.getInitializer();
605
						if (initialization != null) {
606
							this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
607
							if (this.preferences.insert_space_after_assignment_operator) {
608
								this.scribe.space();
609
							}
610
							Alignment2 assignmentAlignment = this.scribe.createAlignment("fieldDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
611
							this.scribe.enterAlignment(assignmentAlignment);
612
							boolean ok2 = false;
613
							do {
614
								try {
615
									this.scribe.alignFragment(assignmentAlignment, 0);
616
									initialization.accept(this);
617
									ok2 = true;
618
								} catch(AlignmentException e){
619
									this.scribe.redoAlignment(e);
620
								}
621
							} while (!ok2);		
622
							this.scribe.exitAlignment(assignmentAlignment, true);			
623
						}
624
						
625
						if (i != fragmentsLength - 1) {
626
							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, insertSpaceBeforeComma);
627
							this.scribe.printTrailingComment();
628
							this.scribe.alignFragment(multiFieldDeclarationsAlignment, i);
629
630
							if (insertSpaceAfterComma) {
631
								this.scribe.space();
632
							}
633
						}
634
					}
635
					ok = true;
636
				} catch (AlignmentException e) {
637
					this.scribe.redoAlignment(e);
638
				}
639
			} while (!ok);
640
			this.scribe.exitAlignment(multiFieldDeclarationsAlignment, true);				
641
		} else {
642
			// single field declaration
643
			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
644
			VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
645
			final int extraDimensions = fragment.getExtraDimensions();
646
			if (extraDimensions != 0) {
647
				for (int i = 0; i < extraDimensions; i++) {
648
					this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
649
					this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
650
				}
651
			}
652
			final Expression initialization = fragment.getInitializer();
653
			if (initialization != null) {
654
				this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
655
				if (this.preferences.insert_space_after_assignment_operator) {
656
					this.scribe.space();
657
				}
658
				Alignment2 assignmentAlignment = this.scribe.createAlignment("localDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
659
				this.scribe.enterAlignment(assignmentAlignment);
660
				boolean ok = false;
661
				do {
662
					try {
663
						this.scribe.alignFragment(assignmentAlignment, 0);
664
						initialization.accept(this);
665
						ok = true;
666
					} catch(AlignmentException e){
667
						this.scribe.redoAlignment(e);
668
					}
669
				} while (!ok);		
670
				this.scribe.exitAlignment(assignmentAlignment, true);			
671
			}
672
		}
673
	}
674
675
	private void formatOpeningBrace(String bracePosition, boolean insertSpaceBeforeBrace) {
676
		if (DefaultCodeFormatterConstants.NEXT_LINE.equals(bracePosition)) {
677
			this.scribe.printNewLine();
678
		} else if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(bracePosition)) {
679
			this.scribe.printNewLine();
680
			this.scribe.indent();
681
		}
682
		this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, insertSpaceBeforeBrace);
683
684
		this.scribe.printTrailingComment();
685
	}
686
	
687
	private void formatStatements(final List statements, boolean insertNewLineAfterLastStatement) {
688
		final int statementsLength = statements.size();
689
		if (statementsLength > 1) {
690
			Statement previousStatement = (Statement) statements.get(0);
691
			previousStatement.accept(this);
692
			final int previousStatementNodeType = previousStatement.getNodeType();
693
			for (int i = 1; i < statementsLength - 1; i++) {
694
				final Statement statement = (Statement) statements.get(i);
695
				final int statementNodeType = statement.getNodeType();
696
				if ((previousStatementNodeType == ASTNode.EMPTY_STATEMENT
697
						&& statementNodeType != ASTNode.EMPTY_STATEMENT)
698
					|| (previousStatementNodeType != ASTNode.EMPTY_STATEMENT
699
						&& statementNodeType != ASTNode.EMPTY_STATEMENT)) {
700
					this.scribe.printNewLine();
701
				}
702
				statement.accept(this);
703
				previousStatement = statement;
704
			}
705
			final Statement statement = ((Statement) statements.get(statementsLength - 1));
706
			final int statementNodeType = statement.getNodeType();
707
			if ((previousStatementNodeType == ASTNode.EMPTY_STATEMENT
708
					&& statementNodeType != ASTNode.EMPTY_STATEMENT)
709
				|| (previousStatementNodeType != ASTNode.EMPTY_STATEMENT
710
					&& statementNodeType != ASTNode.EMPTY_STATEMENT)) {
711
				this.scribe.printNewLine();
712
			}
713
			statement.accept(this);
714
		} else {
715
			((Statement) statements.get(0)).accept(this);
716
		}
717
		if (insertNewLineAfterLastStatement) {
718
			this.scribe.printNewLine();
719
		}
720
	}
721
722
	private void formatTypeMembers(List bodyDeclarations, boolean insertLineAfterLastMember) {
723
		Alignment2 memberAlignment = this.scribe.createMemberAlignment("typeMembers", this.preferences.align_type_members_on_columns ? Alignment.M_MULTICOLUMN : Alignment.M_NO_ALIGNMENT, 3, this.scribe.scanner.currentPosition); //$NON-NLS-1$
724
		this.scribe.enterMemberAlignment(memberAlignment);
725
		boolean isChunkStart = false;
726
		boolean ok = false;
727
		int startIndex = 0;
728
		do {
729
			try {
730
				for (int i = startIndex, max = bodyDeclarations.size(); i < max; i++) {
731
					BodyDeclaration bodyDeclaration = (BodyDeclaration) bodyDeclarations.get(i);
732
					switch(bodyDeclaration.getNodeType()) {
733
						case ASTNode.FIELD_DECLARATION :
734
							isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_FIELD, i, this.scribe.scanner.currentPosition);
735
							FieldDeclaration fieldDeclaration = (FieldDeclaration) bodyDeclaration;
736
							format(fieldDeclaration, isChunkStart, i == 0);
737
							break;
738
						case ASTNode.INITIALIZER :
739
							isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_FIELD, i, this.scribe.scanner.currentPosition);
740
							int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
741
							if (newLineBeforeChunk > 0 && i != 0) {
742
								this.scribe.printEmptyLines(newLineBeforeChunk);
743
							} else if (i == 0) {
744
								int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
745
								if (newLinesBeforeFirstClassBodyDeclaration > 0) {
746
									this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
747
								}
748
							}
749
							bodyDeclaration.accept(this);			
750
							break;
751
						case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION :
752
						case ASTNode.METHOD_DECLARATION :
753
							isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_METHOD, i, this.scribe.scanner.currentPosition);
754
							format(bodyDeclaration, isChunkStart, i == 0);
755
							break;
756
						case ASTNode.TYPE_DECLARATION :
757
						case ASTNode.ENUM_DECLARATION :
758
						case ASTNode.ANNOTATION_TYPE_DECLARATION :
759
							isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_TYPE, i, this.scribe.scanner.currentPosition);
760
							format((AbstractTypeDeclaration)bodyDeclaration, isChunkStart, i == 0);
761
					}
762
					if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
763
						this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
764
						this.scribe.printTrailingComment();
765
					}
766
					if (i < max - 1 || insertLineAfterLastMember) {
767
						this.scribe.printNewLine();
768
					}					
769
					// realign to the proper value
770
					if (this.scribe.memberAlignment != null) {
771
						// select the last alignment
772
						this.scribe.indentationLevel = this.scribe.memberAlignment.originalIndentationLevel;
773
					}
774
				}
775
				ok = true;
776
			} catch(AlignmentException e){
777
				startIndex = memberAlignment.chunkStartIndex;
778
				this.scribe.redoMemberAlignment(e);
779
			}
780
		} while (!ok);
781
		this.scribe.printComment();
782
		this.scribe.exitMemberAlignment(memberAlignment);
783
	}
784
785
	private void formatTypeOpeningBrace(String bracePosition, boolean insertSpaceBeforeBrace, boolean insertNewLine, ASTNode node) {
786
		formatOpeningBrace(bracePosition, insertSpaceBeforeBrace);
787
		if (!insertNewLine) {
788
			switch(node.getNodeType()) {
789
				case ASTNode.ENUM_DECLARATION :
790
					insertNewLine = this.preferences.insert_new_line_in_empty_enum_declaration;
791
					break;
792
				case ASTNode.ENUM_CONSTANT_DECLARATION :
793
					insertNewLine = this.preferences.insert_new_line_in_empty_enum_constant;
794
					break;
795
				case ASTNode.ANONYMOUS_CLASS_DECLARATION :
796
					insertNewLine = this.preferences.insert_new_line_in_empty_anonymous_type_declaration;
797
					break;
798
				case ASTNode.ANNOTATION_TYPE_DECLARATION :
799
					insertNewLine = this.preferences.insert_new_line_in_empty_annotation_declaration;
800
					break;
801
				default:
802
					insertNewLine = this.preferences.insert_new_line_in_empty_type_declaration;
803
			}
804
		}
805
		if (insertNewLine) {
806
			this.scribe.printNewLine();
807
		}
808
	}
809
810
811
	private boolean hasComments() {
812
813
		this.localScanner.resetTo(this.scribe.scanner.startPosition, this.scribe.scannerEndPosition - 1);
814
		try {
815
			switch(this.localScanner.getNextToken()) {
816
				case TerminalTokens.TokenNameCOMMENT_BLOCK :
817
				case TerminalTokens.TokenNameCOMMENT_JAVADOC :
818
				case TerminalTokens.TokenNameCOMMENT_LINE :
819
					return true;
820
			}
821
		} catch(InvalidInputException e) {
822
			// ignore
823
		}
824
		return false;
825
	}
826
	
827
	private boolean isClosingGenericToken() {
828
		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
829
		try {
830
			int token = this.localScanner.getNextToken();
831
			loop: while(true) {
832
				switch(token) {
833
					case TerminalTokens.TokenNameCOMMENT_BLOCK :
834
					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
835
					case TerminalTokens.TokenNameCOMMENT_LINE :
836
						token = this.localScanner.getNextToken();
837
						continue loop;
838
					default:
839
						break loop;
840
				}
841
			}
842
			switch(token) {
843
				case TerminalTokens.TokenNameGREATER :
844
				case TerminalTokens.TokenNameRIGHT_SHIFT :
845
				case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT :
846
					return true;
847
			}
848
		} catch(InvalidInputException e) {
849
			// ignore
850
		}
851
		return false;
852
	}
853
854
	private boolean isGuardClause(Block block, List statements) {
855
		if (commentStartsBlock(block.getStartPosition(), block.getStartPosition() + block.getLength() - 1)) return false;
856
		final int statementsLength = statements.size();
857
		if (statementsLength != 1) return false;
858
		switch(((Statement) statements.get(0)).getNodeType()) {
859
			case ASTNode.RETURN_STATEMENT :
860
			case ASTNode.THROW_STATEMENT :
861
				return true;
862
		}
863
		return false;
864
	}
865
866
	private boolean isNextToken(int tokenName) {
867
		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
868
		try {
869
			int token = this.localScanner.getNextToken();
870
			loop: while(true) {
871
				switch(token) {
872
					case TerminalTokens.TokenNameCOMMENT_BLOCK :
873
					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
874
					case TerminalTokens.TokenNameCOMMENT_LINE :
875
						token = this.localScanner.getNextToken();
876
						continue loop;
877
					default:
878
						break loop;
879
				}
880
			}
881
			return  token == tokenName;
882
		} catch(InvalidInputException e) {
883
			// ignore
884
		}
885
		return false;
886
	}
887
888
	public boolean visit(AnnotationTypeDeclaration node) {
889
        this.scribe.printComment();
890
        final int line = this.scribe.line; 
891
        
892
        final List modifiers = node.modifiers();
893
        if (modifiers.size() != 0) {
894
        	this.scribe.printModifiers(modifiers, this);
895
        	this.scribe.space();
896
        }
897
        this.scribe.printNextToken(TerminalTokens.TokenNameAT, this.preferences.insert_space_before_at_in_annotation_type_declaration);
898
		this.scribe.printNextToken(TerminalTokens.TokenNameinterface, this.preferences.insert_space_after_at_in_annotation_type_declaration); 
899
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
900
901
		String class_declaration_brace;
902
		boolean space_before_opening_brace;
903
		class_declaration_brace = this.preferences.brace_position_for_annotation_type_declaration;
904
		space_before_opening_brace =  this.preferences.insert_space_before_opening_brace_in_annotation_type_declaration;
905
906
		formatLeftCurlyBrace(line, class_declaration_brace);
907
		final List bodyDeclarations = node.bodyDeclarations();
908
		formatTypeOpeningBrace(class_declaration_brace, space_before_opening_brace, bodyDeclarations.size() != 0, node);
909
		
910
		boolean indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_annotation_declaration_header;
911
		if (indent_body_declarations_compare_to_header) {
912
			this.scribe.indent();
913
		}
914
		
915
		formatTypeMembers(bodyDeclarations, true);
916
		
917
		if (indent_body_declarations_compare_to_header) {
918
			this.scribe.unIndent();
919
		}
920
		
921
		if (this.preferences.insert_new_line_in_empty_annotation_declaration) {
922
			this.scribe.printNewLine();
923
		}
924
		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
925
		this.scribe.printTrailingComment();
926
		if (class_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
927
			this.scribe.unIndent();
928
		}
929
		if (hasComments()) {
930
			this.scribe.printNewLine();
931
		}
932
		return false;
933
	}
934
935
	public boolean visit(AnnotationTypeMemberDeclaration node) {        
936
        /*
937
         * Print comments to get proper line number
938
         */
939
        this.scribe.printComment();
940
        List modifiers = node.modifiers();
941
        if (modifiers.size() != 0) {
942
        	this.scribe.printModifiers(modifiers, this);
943
    		this.scribe.space();
944
        }
945
		/*
946
		 * Print the method return type
947
		 */
948
        node.getType().accept(this);
949
		/*
950
		 * Print the method name
951
		 */
952
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
953
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation_type_member_declaration); 
954
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_annotation_type_member_declaration); 
955
956
		Expression defaultValue = node.getDefault();
957
		if (defaultValue != null) {
958
			this.scribe.printNextToken(TerminalTokens.TokenNamedefault, true);
959
			this.scribe.space();
960
			defaultValue.accept(this);
961
		}
962
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
963
		this.scribe.printTrailingComment();
964
		return false;
965
	}
966
967
	public boolean visit(AnonymousClassDeclaration node) {
968
		/*
969
		 * Type body
970
		 */
971
		String anonymous_type_declaration_brace_position = this.preferences.brace_position_for_anonymous_type_declaration;
972
		
973
		final List bodyDeclarations = node.bodyDeclarations();
974
		formatTypeOpeningBrace(anonymous_type_declaration_brace_position, this.preferences.insert_space_before_opening_brace_in_anonymous_type_declaration, bodyDeclarations.size() != 0, node);
975
		
976
		this.scribe.indent();
977
978
		formatTypeMembers(bodyDeclarations, true);
979
980
		this.scribe.unIndent();
981
		if (this.preferences.insert_new_line_in_empty_anonymous_type_declaration) {
982
			this.scribe.printNewLine();
983
		}
984
		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
985
		if (anonymous_type_declaration_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
986
			this.scribe.unIndent();
987
		}
988
		return false;
989
	}
990
991
	public boolean visit(ArrayAccess node) {
992
		node.getArray().accept(this);
993
		this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_opening_bracket_in_array_reference);
994
		if (this.preferences.insert_space_after_opening_bracket_in_array_reference) {
995
			this.scribe.space();
996
		}
997
		node.getIndex().accept(this);
998
		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_before_closing_bracket_in_array_reference);
999
		return false;
1000
	}
1001
1002
	public boolean visit(ArrayCreation node) {
1003
		this.scribe.printNextToken(TerminalTokens.TokenNamenew);
1004
		this.scribe.space();
1005
		final ArrayType type = node.getType();
1006
		final List dimensions = node.dimensions();
1007
		final int dimensionsLength = dimensions.size();
1008
1009
		final int arrayTypeDimensions = type.getDimensions();
1010
		type.getElementType().accept(this);
1011
		if (dimensionsLength != 0) {
1012
			for (int i = 0; i < dimensionsLength; i++) {
1013
				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_opening_bracket_in_array_allocation_expression);
1014
				Expression dimension = (Expression) dimensions.get(i);
1015
				if (dimension != null) {
1016
					if (this.preferences.insert_space_after_opening_bracket_in_array_allocation_expression) {
1017
						this.scribe.space();
1018
					}
1019
					dimension.accept(this);
1020
					this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_before_closing_bracket_in_array_allocation_expression);
1021
				} else {
1022
					this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_between_empty_brackets_in_array_allocation_expression);
1023
				}
1024
			}
1025
			for (int i = 0, max = arrayTypeDimensions - dimensionsLength; i < max; i++) {
1026
				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_opening_bracket_in_array_allocation_expression);
1027
				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_between_empty_brackets_in_array_allocation_expression);
1028
			}
1029
		} else {
1030
			for (int i = 0; i < arrayTypeDimensions; i++) {
1031
				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_opening_bracket_in_array_allocation_expression);
1032
				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_between_empty_brackets_in_array_allocation_expression);
1033
			}
1034
		}
1035
		
1036
		final ArrayInitializer initializer = node.getInitializer();
1037
		if (initializer != null) {
1038
			initializer.accept(this);
1039
		}
1040
1041
		return false;
1042
	}
1043
1044
	public boolean visit(ArrayInitializer node) {
1045
		final List expressions = node.expressions();
1046
		final int expressionsLength = expressions.size();
1047
		if (expressionsLength != 0) {
1048
			final String array_initializer_brace_position = this.preferences.brace_position_for_array_initializer;
1049
			formatOpeningBrace(array_initializer_brace_position, this.preferences.insert_space_before_opening_brace_in_array_initializer);
1050
		
1051
			final boolean insert_new_line_after_opening_brace = this.preferences.insert_new_line_after_opening_brace_in_array_initializer;
1052
			if (expressionsLength > 1) {
1053
				if (insert_new_line_after_opening_brace) {
1054
					this.scribe.printNewLine();
1055
				}
1056
				Alignment2 arrayInitializerAlignment = this.scribe.createAlignment(
1057
						"array_initializer",//$NON-NLS-1$
1058
						this.preferences.alignment_for_expressions_in_array_initializer,
1059
						Alignment.R_OUTERMOST,
1060
						expressionsLength,
1061
						this.scribe.scanner.currentPosition,
1062
						this.preferences.continuation_indentation_for_array_initializer,
1063
						true);
1064
				
1065
				if (insert_new_line_after_opening_brace) {
1066
				    arrayInitializerAlignment.fragmentIndentations[0] = arrayInitializerAlignment.breakIndentationLevel;
1067
				}
1068
				
1069
				this.scribe.enterAlignment(arrayInitializerAlignment);
1070
				boolean ok = false;
1071
				do {
1072
					try {
1073
						this.scribe.alignFragment(arrayInitializerAlignment, 0);
1074
						if (this.preferences.insert_space_after_opening_brace_in_array_initializer) {
1075
							this.scribe.space();
1076
						}
1077
						((Expression) expressions.get(0)).accept(this);
1078
						for (int i = 1; i < expressionsLength; i++) {
1079
							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
1080
							this.scribe.printTrailingComment();
1081
							this.scribe.alignFragment(arrayInitializerAlignment, i);
1082
							if (this.preferences.insert_space_after_comma_in_array_initializer) {
1083
								this.scribe.space();
1084
							}
1085
							((Expression) expressions.get(i)).accept(this);
1086
							if (i == expressionsLength - 1) {
1087
								if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
1088
									this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
1089
									this.scribe.printTrailingComment();
1090
								}
1091
							}
1092
						}
1093
						ok = true;
1094
					} catch (AlignmentException e) {
1095
						this.scribe.redoAlignment(e);
1096
					}
1097
				} while (!ok);
1098
				this.scribe.exitAlignment(arrayInitializerAlignment, true);
1099
			} else {
1100
				if (insert_new_line_after_opening_brace) {
1101
					this.scribe.printNewLine();
1102
					this.scribe.indent();
1103
				}
1104
				// we don't need to use an alignment
1105
				if (this.preferences.insert_space_after_opening_brace_in_array_initializer) {
1106
					this.scribe.space();
1107
				} else {
1108
					this.scribe.needSpace = false;
1109
				}
1110
				((Expression) expressions.get(0)).accept(this);
1111
				if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
1112
					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
1113
					this.scribe.printTrailingComment();
1114
				}
1115
				if (insert_new_line_after_opening_brace) {
1116
					this.scribe.unIndent();
1117
				}
1118
			}
1119
			if (this.preferences.insert_new_line_before_closing_brace_in_array_initializer) {
1120
				this.scribe.printNewLine();
1121
			} else if (this.preferences.insert_space_before_closing_brace_in_array_initializer) {
1122
				this.scribe.space();
1123
			}
1124
			this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, false); 
1125
			if (array_initializer_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
1126
				this.scribe.unIndent();
1127
			}	
1128
		} else {
1129
			boolean keepEmptyArrayInitializerOnTheSameLine = this.preferences.keep_empty_array_initializer_on_one_line;
1130
			String array_initializer_brace_position = this.preferences.brace_position_for_array_initializer;
1131
			if (keepEmptyArrayInitializerOnTheSameLine) {
1132
				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, this.preferences.insert_space_before_opening_brace_in_array_initializer);
1133
				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, this.preferences.insert_space_between_empty_braces_in_array_initializer); 
1134
			} else {
1135
				formatOpeningBrace(array_initializer_brace_position, this.preferences.insert_space_before_opening_brace_in_array_initializer);
1136
				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, false); 
1137
				if (array_initializer_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
1138
					this.scribe.unIndent();
1139
				}
1140
			}
1141
		}
1142
		return false;
1143
	}
1144
1145
	public boolean visit(ArrayType node) {
1146
		node.getComponentType().accept(this);
1147
		if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
1148
			this.scribe.space();
1149
		}
1150
		this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
1151
		if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
1152
			this.scribe.space();
1153
		}
1154
		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
1155
		return false;
1156
	}
1157
1158
	public boolean visit(AssertStatement node) {
1159
		this.scribe.printNextToken(TerminalTokens.TokenNameassert);
1160
		this.scribe.space();
1161
		node.getExpression().accept(this);
1162
		
1163
		Expression message = node.getMessage();
1164
		if (message != null) {
1165
			this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_assert);
1166
			if (this.preferences.insert_space_after_colon_in_assert) {
1167
				this.scribe.space();
1168
			}
1169
			message.accept(this);
1170
		}
1171
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);		
1172
		this.scribe.printTrailingComment();
1173
		return false;
1174
	}
1175
1176
	public boolean visit(Assignment node) {
1177
		node.getLeftHandSide().accept(this);
1178
		Assignment.Operator operator = node.getOperator();
1179
		if (operator == Assignment.Operator.ASSIGN) {
1180
			this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
1181
		} else if (operator == Assignment.Operator.MINUS_ASSIGN) {
1182
			this.scribe.printNextToken(TerminalTokens.TokenNameMINUS_EQUAL, this.preferences.insert_space_before_assignment_operator);
1183
		} else if (operator == Assignment.Operator.PLUS_ASSIGN) {
1184
			this.scribe.printNextToken(TerminalTokens.TokenNamePLUS_EQUAL, this.preferences.insert_space_before_assignment_operator);
1185
		} else if (operator == Assignment.Operator.TIMES_ASSIGN) {
1186
			this.scribe.printNextToken(TerminalTokens.TokenNameMULTIPLY_EQUAL, this.preferences.insert_space_before_assignment_operator);
1187
		} else if (operator == Assignment.Operator.DIVIDE_ASSIGN) {
1188
			this.scribe.printNextToken(TerminalTokens.TokenNameDIVIDE_EQUAL, this.preferences.insert_space_before_assignment_operator);
1189
		} else if (operator == Assignment.Operator.REMAINDER_ASSIGN) {
1190
			this.scribe.printNextToken(TerminalTokens.TokenNameREMAINDER_EQUAL, this.preferences.insert_space_before_assignment_operator);
1191
		} else if (operator == Assignment.Operator.LEFT_SHIFT_ASSIGN) {
1192
			this.scribe.printNextToken(TerminalTokens.TokenNameLEFT_SHIFT_EQUAL, this.preferences.insert_space_before_assignment_operator);
1193
		} else if (operator == Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN) {
1194
			this.scribe.printNextToken(TerminalTokens.TokenNameRIGHT_SHIFT_EQUAL, this.preferences.insert_space_before_assignment_operator);
1195
		} else if (operator == Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN) {
1196
			this.scribe.printNextToken(TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL, this.preferences.insert_space_before_assignment_operator);
1197
		} else if (operator == Assignment.Operator.BIT_AND_ASSIGN) {
1198
			this.scribe.printNextToken(TerminalTokens.TokenNameAND_EQUAL, this.preferences.insert_space_before_assignment_operator);
1199
		} else if (operator == Assignment.Operator.BIT_OR_ASSIGN) {
1200
			this.scribe.printNextToken(TerminalTokens.TokenNameOR_EQUAL, this.preferences.insert_space_before_assignment_operator);
1201
		} else {
1202
			this.scribe.printNextToken(TerminalTokens.TokenNameXOR_EQUAL, this.preferences.insert_space_before_assignment_operator);
1203
		} 
1204
		if (this.preferences.insert_space_after_assignment_operator) {
1205
			this.scribe.space();
1206
		}
1207
1208
		Alignment2 assignmentAlignment = this.scribe.createAlignment("assignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
1209
		this.scribe.enterAlignment(assignmentAlignment);
1210
		boolean ok = false;
1211
		do {
1212
			try {
1213
				this.scribe.alignFragment(assignmentAlignment, 0);
1214
				node.getRightHandSide().accept(this);
1215
				ok = true;
1216
			} catch(AlignmentException e){
1217
				this.scribe.redoAlignment(e);
1218
			}
1219
		} while (!ok);		
1220
		this.scribe.exitAlignment(assignmentAlignment, true);
1221
		return false;
1222
	}
1223
1224
	public boolean visit(Block node) {
1225
		formatBlock(node, this.preferences.brace_position_for_block, this.preferences.insert_space_before_opening_brace_in_block);	
1226
		return false;
1227
	}
1228
1229
	public boolean visit(BooleanLiteral node) {
1230
		if (node.booleanValue()) {
1231
			this.scribe.printNextToken(TerminalTokens.TokenNametrue);
1232
		} else {
1233
			this.scribe.printNextToken(TerminalTokens.TokenNamefalse);
1234
		}
1235
		return false;
1236
	}
1237
1238
	public boolean visit(BreakStatement node) {
1239
		this.scribe.printNextToken(TerminalTokens.TokenNamebreak);
1240
		if (node.getLabel() != null) {
1241
			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
1242
		}
1243
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1244
		this.scribe.printTrailingComment();
1245
		return false;
1246
	}
1247
1248
	public boolean visit(CastExpression node) {
1249
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN);
1250
		if (this.preferences.insert_space_after_opening_paren_in_cast) {
1251
			this.scribe.space();
1252
		}
1253
		node.getType().accept(this);
1254
1255
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_cast);
1256
		if (this.preferences.insert_space_after_closing_paren_in_cast) {
1257
			this.scribe.space();
1258
		}
1259
		node.getExpression().accept(this);
1260
		return false;
1261
	}
1262
1263
	public boolean visit(CharacterLiteral node) {
1264
		this.scribe.printNextToken(TerminalTokens.TokenNameCharacterLiteral);
1265
		return false;
1266
	}
1267
1268
	public boolean visit(ClassInstanceCreation node) {
1269
		Expression expression = node.getExpression();
1270
		if (expression != null) {
1271
			expression.accept(this);
1272
			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
1273
		}
1274
		this.scribe.printNextToken(TerminalTokens.TokenNamenew);
1275
		final List typeArguments = node.typeArguments();
1276
		final int length = typeArguments.size();
1277
		if (length != 0) {
1278
				this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments); 
1279
				if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
1280
					this.scribe.space();
1281
				}
1282
				for (int i = 0; i < length - 1; i++) {
1283
					((Type) typeArguments.get(i)).accept(this);
1284
					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
1285
					if (this.preferences.insert_space_after_comma_in_type_arguments) {
1286
						this.scribe.space();
1287
					}				
1288
				}
1289
				((Type) typeArguments.get(length - 1)).accept(this);
1290
				if (isClosingGenericToken()) {
1291
					this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments); 
1292
				}
1293
				if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
1294
					this.scribe.space();
1295
				}
1296
		} else {
1297
			this.scribe.space();
1298
		}
1299
1300
		node.getType().accept(this);
1301
		
1302
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
1303
1304
		final List arguments = node.arguments();
1305
		final int argumentsLength = arguments.size();
1306
		
1307
		if (argumentsLength != 0) {
1308
			if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
1309
				this.scribe.space();
1310
			}			
1311
			Alignment2 argumentsAlignment =this.scribe.createAlignment(
1312
					"allocation",//$NON-NLS-1$
1313
					this.preferences.alignment_for_arguments_in_allocation_expression,
1314
					argumentsLength,
1315
					this.scribe.scanner.currentPosition);
1316
			this.scribe.enterAlignment(argumentsAlignment);
1317
			boolean ok = false;
1318
			do {
1319
				try {
1320
					for (int i = 0; i < argumentsLength; i++) {
1321
						if (i > 0) {
1322
							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_allocation_expression);
1323
							this.scribe.printTrailingComment();
1324
						}
1325
						this.scribe.alignFragment(argumentsAlignment, i);
1326
						if (i > 0 && this.preferences.insert_space_after_comma_in_allocation_expression) {
1327
							this.scribe.space();
1328
						}
1329
						((Expression) arguments.get(i)).accept(this);
1330
					}
1331
					ok = true;
1332
				} catch (AlignmentException e) {
1333
					this.scribe.redoAlignment(e);
1334
				}
1335
			} while (!ok);
1336
			this.scribe.exitAlignment(argumentsAlignment, true);
1337
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation); 
1338
		} else {
1339
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation); 
1340
		}
1341
		final AnonymousClassDeclaration classDeclaration = node.getAnonymousClassDeclaration();
1342
		if (classDeclaration != null) {
1343
			classDeclaration.accept(this);
1344
		}
1345
		return false;
1346
	}
1347
1348
	public boolean visit(CompilationUnit node) {
1349
		// fake new line to handle empty lines before package declaration or import declarations
1350
		this.scribe.lastNumberOfNewLines = 1;
1351
		/* 
1352
		 * Package declaration
1353
		 */
1354
		final PackageDeclaration packageDeclaration = node.getPackage();
1355
		final boolean hasPackage = packageDeclaration != null;
1356
		if (hasPackage) {
1357
			if (hasComments()) {
1358
				this.scribe.printComment();
1359
			}
1360
			int blankLinesBeforePackage = this.preferences.blank_lines_before_package;
1361
			if (blankLinesBeforePackage > 0) {
1362
				this.scribe.printEmptyLines(blankLinesBeforePackage);
1363
			}
1364
1365
			final List annotations = packageDeclaration.annotations();
1366
			if (annotations.size() != 0) {
1367
				this.scribe.printModifiers(annotations, this);
1368
				this.scribe.space();
1369
			}
1370
			// dump the package keyword
1371
			this.scribe.printNextToken(TerminalTokens.TokenNamepackage);
1372
			this.scribe.space();
1373
			packageDeclaration.getName().accept(this);
1374
			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1375
			this.scribe.printTrailingComment();
1376
			int blankLinesAfterPackage = this.preferences.blank_lines_after_package;
1377
			if (blankLinesAfterPackage > 0) {
1378
				this.scribe.printEmptyLines(blankLinesAfterPackage);
1379
			} else {
1380
				this.scribe.printNewLine();
1381
			}			
1382
		} else {
1383
			this.scribe.printComment();
1384
		}
1385
		
1386
		/*
1387
		 * Import statements
1388
		 */
1389
		final List imports = node.imports();
1390
		final int importsLength = imports.size();
1391
		if (importsLength != 0) {
1392
			if (hasPackage) {
1393
				int blankLinesBeforeImports = this.preferences.blank_lines_before_imports;
1394
				if (blankLinesBeforeImports > 0) {
1395
					this.scribe.printEmptyLines(blankLinesBeforeImports);
1396
				}
1397
			}
1398
			for (int i = 0; i < importsLength; i++) {
1399
				((ImportDeclaration) imports.get(i)).accept(this);
1400
			}			
1401
			
1402
			int blankLinesAfterImports = this.preferences.blank_lines_after_imports;
1403
			if (blankLinesAfterImports > 0) {
1404
				this.scribe.printEmptyLines(blankLinesAfterImports);
1405
			}
1406
		}
1407
1408
		formatEmptyTypeDeclaration(true);
1409
		
1410
		int blankLineBetweenTypeDeclarations = this.preferences.blank_lines_between_type_declarations;
1411
		/*
1412
		 * Type declarations
1413
		 */
1414
		final List types = node.types();
1415
		final int typesLength = types.size();
1416
		if (typesLength != 0) {
1417
			for (int i = 0; i < typesLength - 1; i++) {
1418
				((AbstractTypeDeclaration) types.get(i)).accept(this);
1419
				formatEmptyTypeDeclaration(false);
1420
				if (blankLineBetweenTypeDeclarations != 0) {
1421
					this.scribe.printEmptyLines(blankLineBetweenTypeDeclarations);
1422
				} else {
1423
					this.scribe.printNewLine();
1424
				}
1425
			}
1426
			((AbstractTypeDeclaration) types.get(typesLength - 1)).accept(this);
1427
		}
1428
		this.scribe.printEndOfCompilationUnit();
1429
		return false;
1430
	}
1431
1432
	public boolean visit(ConditionalExpression node) {
1433
		node.getExpression().accept(this);
1434
    
1435
    	Alignment2 conditionalExpressionAlignment =this.scribe.createAlignment(
1436
    			"conditionalExpression", //$NON-NLS-1$
1437
    			this.preferences.alignment_for_conditional_expression,
1438
    			2,
1439
    			this.scribe.scanner.currentPosition);
1440
    
1441
    	this.scribe.enterAlignment(conditionalExpressionAlignment);
1442
    	boolean ok = false;
1443
    	do {
1444
    		try {
1445
    			this.scribe.alignFragment(conditionalExpressionAlignment, 0);
1446
    			this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_conditional);
1447
    
1448
    			if (this.preferences.insert_space_after_question_in_conditional) {
1449
    				this.scribe.space();
1450
    			}
1451
    			node.getThenExpression().accept(this);
1452
    			this.scribe.printTrailingComment();
1453
    			this.scribe.alignFragment(conditionalExpressionAlignment, 1);
1454
    			this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_conditional);
1455
    
1456
    			if (this.preferences.insert_space_after_colon_in_conditional) {
1457
    				this.scribe.space();
1458
    			}
1459
    			node.getElseExpression().accept(this);
1460
    
1461
    			ok = true;
1462
    		} catch (AlignmentException e) {
1463
    			this.scribe.redoAlignment(e);
1464
    		}
1465
    	} while (!ok);
1466
    	this.scribe.exitAlignment(conditionalExpressionAlignment, true);
1467
    	return false;	
1468
    }
1469
1470
	public boolean visit(ConstructorInvocation node) {
1471
		final List typeArguments = node.typeArguments();
1472
		final int typeArgumentsLength = typeArguments.size();
1473
		if (typeArgumentsLength != 0) {
1474
				this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments); 
1475
				if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
1476
					this.scribe.space();
1477
				}
1478
				for (int i = 0; i < typeArgumentsLength - 1; i++) {
1479
					((Type) typeArguments.get(i)).accept(this);
1480
					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
1481
					if (this.preferences.insert_space_after_comma_in_type_arguments) {
1482
						this.scribe.space();
1483
					}				
1484
				}
1485
				((Type) typeArguments.get(typeArgumentsLength - 1)).accept(this);
1486
				if (isClosingGenericToken()) {
1487
					this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments); 
1488
				}
1489
				if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
1490
					this.scribe.space();
1491
				}
1492
		}
1493
		
1494
		this.scribe.printNextToken(TerminalTokens.TokenNamethis);
1495
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
1496
		
1497
		final List arguments = node.arguments();
1498
		final int argumentsLength = arguments.size();
1499
		if (argumentsLength != 0) {
1500
			if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
1501
				this.scribe.space();
1502
			}
1503
			Alignment2 argumentsAlignment =this.scribe.createAlignment(
1504
					"explicit_constructor_call",//$NON-NLS-1$
1505
					this.preferences.alignment_for_arguments_in_explicit_constructor_call,
1506
					argumentsLength,
1507
					this.scribe.scanner.currentPosition);
1508
			this.scribe.enterAlignment(argumentsAlignment);
1509
			boolean ok = false;
1510
			do {
1511
				try {
1512
					for (int i = 0; i < argumentsLength; i++) {
1513
						if (i > 0) {
1514
							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_explicit_constructor_call_arguments);
1515
							this.scribe.printTrailingComment();
1516
						}
1517
						this.scribe.alignFragment(argumentsAlignment, i);
1518
						if (i > 0 && this.preferences.insert_space_after_comma_in_explicit_constructor_call_arguments) {
1519
							this.scribe.space();
1520
						}
1521
						((Expression) arguments.get(i)).accept(this);
1522
					}
1523
					ok = true;
1524
				} catch (AlignmentException e) {
1525
					this.scribe.redoAlignment(e);
1526
				}
1527
			} while (!ok);
1528
			this.scribe.exitAlignment(argumentsAlignment, true);
1529
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation); 
1530
		} else {
1531
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation); 
1532
		}
1533
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1534
		this.scribe.printTrailingComment();
1535
		return false;
1536
	}
1537
1538
	public boolean visit(ContinueStatement node) {
1539
		this.scribe.printNextToken(TerminalTokens.TokenNamecontinue);
1540
		if (node.getLabel() != null) {
1541
			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
1542
		}
1543
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1544
		this.scribe.printTrailingComment();
1545
		return false;
1546
	}
1547
1548
	public boolean visit(DoStatement node) {
1549
		this.scribe.printNextToken(TerminalTokens.TokenNamedo);
1550
		final int line = this.scribe.line;
1551
		
1552
		final Statement action = node.getBody();
1553
		if (action != null) {
1554
			switch(action.getNodeType()) {
1555
				case ASTNode.BLOCK :
1556
	                formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
1557
					action.accept(this);
1558
					break;
1559
				case ASTNode.EMPTY_STATEMENT :
1560
					action.accept(this);
1561
					break;
1562
				default :
1563
					this.scribe.printNewLine();
1564
					this.scribe.indent();
1565
					action.accept(this);
1566
					this.scribe.unIndent();
1567
					this.scribe.printNewLine();
1568
			}
1569
		}
1570
1571
		if (this.preferences.insert_new_line_before_while_in_do_statement) {
1572
			this.scribe.printNewLine();
1573
		}
1574
		this.scribe.printNextToken(TerminalTokens.TokenNamewhile, this.preferences.insert_space_after_closing_brace_in_block);
1575
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_while);
1576
		
1577
		if (this.preferences.insert_space_after_opening_paren_in_while) {
1578
			this.scribe.space();
1579
		}
1580
		
1581
		node.getExpression().accept(this);
1582
		
1583
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_while);
1584
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1585
		this.scribe.printTrailingComment();
1586
		return false;
1587
	}
1588
1589
	public boolean visit(EmptyStatement node) {
1590
		if (this.preferences.put_empty_statement_on_new_line) {
1591
			this.scribe.printNewLine();
1592
		}
1593
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1594
		this.scribe.printTrailingComment();
1595
		return false;
1596
	}
1597
1598
	public boolean visit(EnhancedForStatement node) {
1599
		this.scribe.printNextToken(TerminalTokens.TokenNamefor);
1600
	    final int line = this.scribe.line;
1601
	    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_for);
1602
		
1603
		if (this.preferences.insert_space_after_opening_paren_in_for) {
1604
			this.scribe.space();
1605
		}
1606
		node.getParameter().accept(this);
1607
1608
		this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_for);
1609
		if (this.preferences.insert_space_after_colon_in_for) {
1610
			this.scribe.space();
1611
		}
1612
		node.getExpression().accept(this);
1613
1614
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_for);
1615
		
1616
		formatAction(line, node.getBody(), false);
1617
		return false;
1618
	}
1619
1620
	public boolean visit(EnumConstantDeclaration node) {
1621
        this.scribe.printComment();
1622
        final int line = this.scribe.line; 
1623
        
1624
        final List modifiers = node.modifiers();
1625
        if (modifiers.size() != 0) {
1626
            this.scribe.printModifiers(modifiers, this);
1627
            this.scribe.space();
1628
        }
1629
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
1630
		if (isNextToken(TerminalTokens.TokenNameLPAREN)) {
1631
			this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_enum_constant);
1632
			final List arguments = node.arguments();
1633
			final int argumentsLength = arguments.size();
1634
			if (argumentsLength != 0) {
1635
				Alignment2 argumentsAlignment = this.scribe.createAlignment(
1636
						"enumConstantArguments",//$NON-NLS-1$
1637
						this.preferences.alignment_for_arguments_in_enum_constant,
1638
						argumentsLength,
1639
						this.scribe.scanner.currentPosition);
1640
				this.scribe.enterAlignment(argumentsAlignment);
1641
				boolean ok = false;
1642
				do {
1643
					try {
1644
						if (this.preferences.insert_space_after_opening_paren_in_enum_constant) {
1645
							this.scribe.space();
1646
						}
1647
						for (int i = 0; i < argumentsLength; i++) {
1648
							if (i > 0) {
1649
								this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_constant_arguments);
1650
								this.scribe.printTrailingComment();
1651
							}
1652
							this.scribe.alignFragment(argumentsAlignment, i);
1653
							if (i > 0 && this.preferences.insert_space_after_comma_in_enum_constant_arguments) {
1654
								this.scribe.space();
1655
							}
1656
							((Expression) arguments.get(i)).accept(this);
1657
						}
1658
						ok = true;
1659
					} catch (AlignmentException e) {
1660
						this.scribe.redoAlignment(e);
1661
					}
1662
				} while (!ok);
1663
				this.scribe.exitAlignment(argumentsAlignment, true);
1664
			
1665
				this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_enum_constant); 
1666
			} else {
1667
				this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_enum_constant); 
1668
			}
1669
		}
1670
1671
		final AnonymousClassDeclaration anonymousClassDeclaration = node.getAnonymousClassDeclaration();
1672
		if (anonymousClassDeclaration != null) {
1673
			final List bodyDeclarations = anonymousClassDeclaration.bodyDeclarations();
1674
			String enum_constant_brace = this.preferences.brace_position_for_enum_constant;
1675
			
1676
	        formatLeftCurlyBrace(line, enum_constant_brace);
1677
			formatTypeOpeningBrace(enum_constant_brace, this.preferences.insert_space_before_opening_brace_in_enum_constant, bodyDeclarations.size() != 0, node);
1678
			
1679
			if (this.preferences.indent_body_declarations_compare_to_enum_constant_header) {
1680
				this.scribe.indent();
1681
			}
1682
1683
			formatTypeMembers(bodyDeclarations, true);
1684
1685
			if (this.preferences.indent_body_declarations_compare_to_enum_constant_header) {
1686
				this.scribe.unIndent();
1687
			}
1688
			
1689
			if (this.preferences.insert_new_line_in_empty_enum_constant) {
1690
				this.scribe.printNewLine();
1691
			}
1692
			this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
1693
			if (enum_constant_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
1694
				this.scribe.unIndent();
1695
			}
1696
			if (hasComments()) {
1697
				this.scribe.printNewLine();
1698
			}
1699
		}
1700
		return false;
1701
	}
1702
	
1703
    
1704
	public boolean visit(EnumDeclaration node) {
1705
        /*
1706
         * Print comments to get proper line number
1707
         */
1708
        this.scribe.printComment();
1709
        final int line = this.scribe.line; 
1710
        
1711
        final List modifiers = node.modifiers();
1712
        if (modifiers.size() != 0) {
1713
        	this.scribe.printModifiers(modifiers, this);
1714
        	this.scribe.space();
1715
        }
1716
        	
1717
		this.scribe.printNextToken(TerminalTokens.TokenNameenum, true); 
1718
1719
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
1720
1721
		/* 
1722
		 * Super Interfaces 
1723
		 */
1724
		final List superInterfaces = node.superInterfaceTypes();
1725
		final int superInterfacesLength = superInterfaces.size();
1726
		if (superInterfacesLength != 0) {
1727
			Alignment2 interfaceAlignment =this.scribe.createAlignment(
1728
					"superInterfaces",//$NON-NLS-1$
1729
					this.preferences.alignment_for_superinterfaces_in_enum_declaration,
1730
					superInterfacesLength+1,  // implements token is first fragment
1731
					this.scribe.scanner.currentPosition);
1732
			this.scribe.enterAlignment(interfaceAlignment);
1733
			boolean ok = false;
1734
			do {
1735
				try {
1736
					this.scribe.alignFragment(interfaceAlignment, 0);
1737
					this.scribe.printNextToken(TerminalTokens.TokenNameimplements, true);
1738
					for (int i = 0; i < superInterfacesLength; i++) {
1739
						if (i > 0) {
1740
							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_superinterfaces);
1741
							this.scribe.printTrailingComment();
1742
							this.scribe.alignFragment(interfaceAlignment, i+1);
1743
							if (this.preferences.insert_space_after_comma_in_superinterfaces) {
1744
								this.scribe.space();
1745
							}
1746
							((Type) superInterfaces.get(i)).accept(this);
1747
						} else {
1748
							this.scribe.alignFragment(interfaceAlignment, i+1);
1749
							this.scribe.space();
1750
							((Type) superInterfaces.get(i)).accept(this);
1751
						}
1752
					}
1753
					ok = true;
1754
				} catch (AlignmentException e) {
1755
					this.scribe.redoAlignment(e);
1756
				}
1757
			} while (!ok);
1758
			this.scribe.exitAlignment(interfaceAlignment, true);
1759
		}
1760
		
1761
		final String bracePosition = this.preferences.brace_position_for_enum_declaration;
1762
1763
		final List enumConstants = node.enumConstants();
1764
		final int enumConstantsLength = enumConstants.size();
1765
1766
		formatLeftCurlyBrace(line, bracePosition);
1767
		formatTypeOpeningBrace(bracePosition, this.preferences.insert_space_before_opening_brace_in_enum_declaration, (enumConstantsLength + node.bodyDeclarations().size()) != 0, node);
1768
		
1769
		final boolean indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_enum_declaration_header;
1770
		if (indent_body_declarations_compare_to_header) {
1771
			this.scribe.indent();
1772
		}
1773
		
1774
		if (enumConstantsLength != 0) {
1775
			if (enumConstantsLength > 1) {
1776
				Alignment2 enumConstantsAlignment = this.scribe.createAlignment(
1777
						"enumConstants",//$NON-NLS-1$
1778
						this.preferences.alignment_for_enum_constants,
1779
						enumConstantsLength,
1780
						this.scribe.scanner.currentPosition,
1781
						0, // we don't want to indent enum constants when splitting to a new line
1782
						false);
1783
				this.scribe.enterAlignment(enumConstantsAlignment);
1784
				boolean ok = false;
1785
				do {
1786
					try {
1787
						for (int i = 0; i < enumConstantsLength; i++) {
1788
							this.scribe.alignFragment(enumConstantsAlignment, i);
1789
							final EnumConstantDeclaration enumConstantDeclaration = ((EnumConstantDeclaration) enumConstants.get(i));
1790
							enumConstantDeclaration.accept(this);
1791
							if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
1792
								this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_declarations);
1793
								if (this.preferences.insert_space_after_comma_in_enum_declarations) {
1794
									this.scribe.space();
1795
								}
1796
								this.scribe.printTrailingComment();
1797
								if (enumConstantDeclaration.getAnonymousClassDeclaration() != null) {
1798
									this.scribe.printNewLine();
1799
								}
1800
							}
1801
						}
1802
						ok = true;
1803
					} catch (AlignmentException e) {
1804
						this.scribe.redoAlignment(e);
1805
					}
1806
				} while (!ok);
1807
				this.scribe.exitAlignment(enumConstantsAlignment, true);
1808
			} else {
1809
				final EnumConstantDeclaration enumConstantDeclaration = ((EnumConstantDeclaration) enumConstants.get(0));
1810
				enumConstantDeclaration.accept(this);
1811
				if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
1812
					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_declarations);
1813
					if (this.preferences.insert_space_after_comma_in_enum_declarations) {
1814
						this.scribe.space();
1815
					}
1816
					this.scribe.printTrailingComment();
1817
					if (enumConstantDeclaration.getAnonymousClassDeclaration() != null) {
1818
						this.scribe.printNewLine();
1819
					}
1820
				}
1821
			}
1822
		}
1823
		if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
1824
			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1825
			this.scribe.printTrailingComment();
1826
		}
1827
		if (enumConstantsLength != 0) {
1828
			this.scribe.printNewLine();	
1829
		}
1830
1831
		formatTypeMembers(node.bodyDeclarations(), true);
1832
		
1833
		if (indent_body_declarations_compare_to_header) {
1834
			this.scribe.unIndent();
1835
		}
1836
		
1837
		if (this.preferences.insert_new_line_in_empty_enum_declaration) {
1838
			this.scribe.printNewLine();
1839
		}
1840
		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
1841
		this.scribe.printTrailingComment();
1842
		if (bracePosition.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
1843
			this.scribe.unIndent();
1844
		}
1845
		if (hasComments()) {
1846
			this.scribe.printNewLine();
1847
		}
1848
		return false;
1849
	}	
1850
1851
	public boolean visit(ExpressionStatement node) {
1852
		node.getExpression().accept(this);
1853
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1854
		this.scribe.printTrailingComment();
1855
		return false;
1856
	}
1857
1858
	public boolean visit(FieldAccess node) {
1859
		node.getExpression().accept(this);
1860
		this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
1861
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
1862
		return false;
1863
	}
1864
1865
	public boolean visit(ForStatement node) {
1866
		this.scribe.printNextToken(TerminalTokens.TokenNamefor);
1867
	    final int line = this.scribe.line;
1868
	    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_for);
1869
		
1870
		if (this.preferences.insert_space_after_opening_paren_in_for) {
1871
			this.scribe.space();
1872
		}
1873
		final List initializers = node.initializers();
1874
		final int initializersLength = initializers.size();
1875
		if (initializersLength != 0) {
1876
			for (int i = 0; i < initializersLength; i++) {
1877
				Expression initializer = (Expression) initializers.get(i);
1878
				switch(initializer.getNodeType()) {
1879
					case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
1880
						formatLocalDeclaration((VariableDeclarationExpression) initializer, this.preferences.insert_space_before_comma_in_for_inits, this.preferences.insert_space_after_comma_in_for_inits);
1881
						break;
1882
					default:
1883
						initializer.accept(this);
1884
						if (i >= 0 && (i < initializersLength - 1)) {
1885
							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_for_inits);
1886
							if (this.preferences.insert_space_after_comma_in_for_inits) {
1887
								this.scribe.space();
1888
							}
1889
							this.scribe.printTrailingComment();
1890
						}
1891
				}
1892
			}
1893
		}
1894
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon_in_for);
1895
		final Expression condition = node.getExpression();
1896
		if (condition != null) {
1897
			if (this.preferences.insert_space_after_semicolon_in_for) {
1898
				this.scribe.space();
1899
			}
1900
			condition.accept(this);
1901
		}
1902
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon_in_for);
1903
		final List updaters = node.updaters();
1904
		final int updatersLength = updaters.size();
1905
		if (updatersLength != 0) {
1906
			if (this.preferences.insert_space_after_semicolon_in_for) {
1907
				this.scribe.space();
1908
			}
1909
			for (int i = 0; i < updatersLength; i++) {
1910
				((Expression) updaters.get(i)).accept(this);
1911
				if (i != updatersLength - 1) {
1912
					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_for_increments);
1913
					if (this.preferences.insert_space_after_comma_in_for_increments) {
1914
						this.scribe.space();
1915
					}
1916
					this.scribe.printTrailingComment();
1917
				}
1918
			}
1919
		}
1920
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_for);
1921
		
1922
		formatAction(line, node.getBody(), false);
1923
		return false;
1924
	}
1925
1926
	public boolean visit(IfStatement node) {
1927
		this.scribe.printNextToken(TerminalTokens.TokenNameif);
1928
        final int line = this.scribe.line;
1929
        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_if);
1930
		if (this.preferences.insert_space_after_opening_paren_in_if) {
1931
			this.scribe.space();
1932
		}
1933
		node.getExpression().accept(this);
1934
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_if);
1935
1936
		final Statement thenStatement = node.getThenStatement();
1937
		final Statement elseStatement = node.getElseStatement();
1938
1939
		boolean thenStatementIsBlock = false;
1940
		if (thenStatement != null) {
1941
			if (thenStatement instanceof Block) {
1942
				final Block block = (Block) thenStatement;
1943
				thenStatementIsBlock = true;
1944
				final List statements = block.statements();
1945
				if (isGuardClause(block, statements) && elseStatement == null && this.preferences.keep_guardian_clause_on_one_line) {
1946
					/* 
1947
					 * Need a specific formatting for guard clauses
1948
					 * guard clauses are block with a single return or throw
1949
					 * statement
1950
					 */
1951
					this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, this.preferences.insert_space_before_opening_brace_in_block);
1952
					this.scribe.space();
1953
					((Statement) statements.get(0)).accept(this);
1954
					this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, true);
1955
					this.scribe.printTrailingComment();
1956
				} else {
1957
                    formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
1958
					thenStatement.accept(this);
1959
					if (elseStatement != null && (this.preferences.insert_new_line_before_else_in_if_statement)) {
1960
						this.scribe.printNewLine();
1961
					}
1962
				}
1963
			} else if (elseStatement == null && this.preferences.keep_simple_if_on_one_line) {
1964
				Alignment2 compactIfAlignment = this.scribe.createAlignment(
1965
						"compactIf", //$NON-NLS-1$
1966
						this.preferences.alignment_for_compact_if,
1967
						Alignment.R_OUTERMOST,
1968
						1,
1969
						this.scribe.scanner.currentPosition,
1970
						1,
1971
						false);
1972
				this.scribe.enterAlignment(compactIfAlignment);
1973
				boolean ok = false;
1974
				do {
1975
					try {
1976
						this.scribe.alignFragment(compactIfAlignment, 0);
1977
						this.scribe.space();
1978
						thenStatement.accept(this);
1979
						ok = true;
1980
					} catch (AlignmentException e) {
1981
						this.scribe.redoAlignment(e);
1982
					}
1983
				} while (!ok);
1984
				this.scribe.exitAlignment(compactIfAlignment, true);				
1985
			} else if (this.preferences.keep_then_statement_on_same_line) {
1986
				this.scribe.space();
1987
				thenStatement.accept(this);
1988
				if (elseStatement != null) {
1989
					this.scribe.printNewLine();
1990
				}
1991
			} else {
1992
				this.scribe.printTrailingComment();
1993
				this.scribe.printNewLine();
1994
				this.scribe.indent();
1995
				thenStatement.accept(this);
1996
				if (elseStatement != null) {
1997
					this.scribe.printNewLine();
1998
				}
1999
				this.scribe.unIndent();
2000
			}
2001
		}
2002
		
2003
		if (elseStatement != null) {
2004
			if (thenStatementIsBlock) {
2005
				this.scribe.printNextToken(TerminalTokens.TokenNameelse, this.preferences.insert_space_after_closing_brace_in_block);
2006
			} else {
2007
				this.scribe.printNextToken(TerminalTokens.TokenNameelse, true);
2008
			}
2009
			if (elseStatement instanceof Block) {
2010
				elseStatement.accept(this);
2011
			} else if (elseStatement instanceof IfStatement) {
2012
				if (!this.preferences.compact_else_if) {
2013
					this.scribe.printNewLine();
2014
					this.scribe.indent();
2015
				}
2016
				this.scribe.space();				
2017
				elseStatement.accept(this);
2018
				if (!this.preferences.compact_else_if) {
2019
					this.scribe.unIndent();
2020
				}
2021
			} else if (this.preferences.keep_else_statement_on_same_line) {
2022
				this.scribe.space();
2023
				elseStatement.accept(this);
2024
			} else {
2025
				this.scribe.printNewLine();
2026
				this.scribe.indent();
2027
				elseStatement.accept(this);
2028
				this.scribe.unIndent();
2029
			}
2030
		}
2031
		return false;
2032
	}
2033
2034
	public boolean visit(ImportDeclaration node) {
2035
		this.scribe.printNextToken(TerminalTokens.TokenNameimport);
2036
		this.scribe.space();
2037
		if (node.isStatic()) {
2038
			this.scribe.printNextToken(TerminalTokens.TokenNamestatic);
2039
			this.scribe.space();
2040
		}
2041
		node.getName().accept(this);
2042
		if (node.isOnDemand()) {
2043
			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2044
			this.scribe.printNextToken(TerminalTokens.TokenNameMULTIPLY);			
2045
		}
2046
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2047
		this.scribe.printTrailingComment();
2048
		this.scribe.printNewLine();
2049
		return false;
2050
	}
2051
2052
	public boolean visit(InfixExpression node) {
2053
		// active line wrapping
2054
		final InfixExpressionWrappingBuilder builder = new InfixExpressionWrappingBuilder();
2055
		node.accept(builder);
2056
		final int fragmentsSize = builder.getFragmentsCounter();
2057
		this.scribe.printComment();
2058
		Alignment2 binaryExpressionAlignment = this.scribe.createAlignment("binaryExpressionAlignment", this.preferences.alignment_for_binary_expression, Alignment.R_OUTERMOST, fragmentsSize, this.scribe.scanner.currentPosition); //$NON-NLS-1$
2059
		this.scribe.enterAlignment(binaryExpressionAlignment);
2060
		boolean ok = false;
2061
		List fragments = builder.fragments;
2062
		int[] operators = builder.getOperators();
2063
/*		do {
2064
			try {
2065
				final boolean alignAfterOperator = false;
2066
				if (alignAfterOperator) {
2067
					for (int i = 0; i < fragmentsSize - 1; i++) {
2068
						this.scribe.alignFragment(binaryExpressionAlignment, i);
2069
						((Expression) fragments.get(i)).accept(this);
2070
						this.scribe.printTrailingComment();
2071
						if (this.scribe.lastNumberOfNewLines == 1) {
2072
							// a new line has been inserted by printTrailingComment()
2073
							this.scribe.indentationLevel = binaryExpressionAlignment.breakIndentationLevel;
2074
						}
2075
						this.scribe.printNextToken(operators[i], this.preferences.insert_space_before_binary_operator);
2076
						if (operators[i] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
2077
							// the next character is a minus (unary operator)
2078
							this.scribe.space();
2079
						}
2080
						if (this.preferences.insert_space_after_binary_operator) {
2081
							this.scribe.space();
2082
						}
2083
					}
2084
					this.scribe.alignFragment(binaryExpressionAlignment, fragmentsSize - 1);
2085
					((Expression) fragments.get(fragmentsSize - 1)).accept(this);
2086
					this.scribe.printTrailingComment();
2087
				} else {
2088
					this.scribe.alignFragment(binaryExpressionAlignment, 0);
2089
					((Expression) fragments.get(0)).accept(this);
2090
					this.scribe.printTrailingComment();
2091
					if (this.scribe.lastNumberOfNewLines == 1) {
2092
						if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2093
							binaryExpressionAlignment.performFragmentEffect();
2094
						}
2095
					}
2096
					for (int i = 1; i < fragmentsSize - 1; i++) {
2097
						this.scribe.alignFragment(binaryExpressionAlignment, i);
2098
						this.scribe.printNextToken(operators[i - 1], this.preferences.insert_space_before_binary_operator);
2099
						if (operators[i] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
2100
							// the next character is a minus (unary operator)
2101
							this.scribe.space();
2102
						}
2103
						if (this.preferences.insert_space_after_binary_operator) {
2104
							this.scribe.space();
2105
						}
2106
						((Expression) fragments.get(i)).accept(this);
2107
						this.scribe.printTrailingComment();
2108
						if (this.scribe.lastNumberOfNewLines == 1) {
2109
							if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2110
								binaryExpressionAlignment.performFragmentEffect();
2111
							}
2112
						}
2113
					}
2114
					this.scribe.alignFragment(binaryExpressionAlignment, fragmentsSize - 1);
2115
					this.scribe.printNextToken(operators[fragmentsSize - 2], this.preferences.insert_space_before_binary_operator);
2116
					if (operators[fragmentsSize - 2] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
2117
						// the next character is a minus (unary operator)
2118
						this.scribe.space();
2119
					}
2120
					if (this.preferences.insert_space_after_binary_operator) {
2121
						this.scribe.space();
2122
					}
2123
					((Expression) fragments.get(fragmentsSize - 1)).accept(this);
2124
					this.scribe.printTrailingComment();
2125
					if (this.scribe.lastNumberOfNewLines == 1) {
2126
						if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2127
							binaryExpressionAlignment.performFragmentEffect();
2128
						}
2129
					}
2130
				}
2131
				ok = true;
2132
			} catch(AlignmentException e){
2133
				this.scribe.redoAlignment(e);
2134
			}
2135
		} while (!ok);
2136
		this.scribe.exitAlignment(binaryExpressionAlignment, true);*/
2137
		do {
2138
			try {
2139
				for (int i = 0; i < fragmentsSize - 1; i++) {
2140
					((Expression) fragments.get(i)).accept(this);
2141
					this.scribe.printTrailingComment();
2142
					if (this.scribe.lastNumberOfNewLines == 1) {
2143
						if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2144
							binaryExpressionAlignment.performFragmentEffect();
2145
						}
2146
					}
2147
					this.scribe.alignFragment(binaryExpressionAlignment, i);
2148
					this.scribe.printNextToken(operators[i], this.preferences.insert_space_before_binary_operator);
2149
					this.scribe.printTrailingComment();
2150
					if (this.scribe.lastNumberOfNewLines == 1) {
2151
						if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2152
							binaryExpressionAlignment.performFragmentEffect();
2153
						}
2154
					}
2155
					if ( this.preferences.insert_space_after_binary_operator
2156
							|| (operators[i] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS))) {
2157
						// the next character is a minus (unary operator) or the preference is set to true
2158
						this.scribe.space();
2159
					}
2160
				}
2161
				((Expression) fragments.get(fragmentsSize - 1)).accept(this);
2162
				this.scribe.printTrailingComment();
2163
				if (this.scribe.lastNumberOfNewLines == 1) {
2164
					if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2165
						binaryExpressionAlignment.performFragmentEffect();
2166
					}
2167
				}
2168
				ok = true;
2169
			} catch(AlignmentException e){
2170
				this.scribe.redoAlignment(e);
2171
			}
2172
		} while (!ok);		
2173
		this.scribe.exitAlignment(binaryExpressionAlignment, true);		
2174
/*			leftOperand.accept(this);
2175
			final int operator = extractInfixExpressionOperator(node);
2176
			this.scribe.printNextToken(operator, this.preferences.insert_space_before_binary_operator);
2177
			if ( this.preferences.insert_space_after_binary_operator
2178
					|| (operator == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS))) {
2179
				// the next character is a minus (unary operator) or the preference is set to true
2180
				this.scribe.space();
2181
			}
2182
			rightOperand.accept(this);*/
2183
		return false;
2184
	}
2185
2186
	public boolean visit(Initializer node) {
2187
		final List modifiers = node.modifiers();
2188
		if (modifiers.size() != 0) {
2189
			this.scribe.printModifiers(modifiers, this);
2190
			this.scribe.space();
2191
		}
2192
		node.getBody().accept(this);
2193
		return false;
2194
	}
2195
2196
	public boolean visit(InstanceofExpression node) {
2197
		node.getLeftOperand().accept(this);
2198
		this.scribe.printNextToken(TerminalTokens.TokenNameinstanceof, true);
2199
		this.scribe.space();
2200
		node.getRightOperand().accept(this);
2201
		return false;
2202
	}
2203
2204
	public boolean visit(LabeledStatement node) {
2205
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
2206
		this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_labeled_statement);
2207
		if (this.preferences.insert_space_after_colon_in_labeled_statement) {
2208
			this.scribe.space();
2209
		}
2210
		node.getBody().accept(this);
2211
		return false;
2212
	}
2213
	
2214
	public boolean visit(MarkerAnnotation node) {
2215
		this.scribe.printNextToken(TerminalTokens.TokenNameAT);
2216
		if (this.preferences.insert_space_after_at_in_annotation) {
2217
			this.scribe.space();
2218
		}
2219
		node.getTypeName().accept(this);
2220
		return false;
2221
	}
2222
2223
	public boolean visit(MemberValuePair node) {
2224
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
2225
		this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
2226
		if (this.preferences.insert_space_after_assignment_operator) {
2227
			this.scribe.space();
2228
		}
2229
		node.getValue().accept(this);	
2230
		return false;
2231
	}
2232
2233
	public boolean visit(MethodDeclaration node) {
2234
		if ((node.getFlags() & ASTNode.MALFORMED) != 0) {
2235
			this.scribe.printComment();
2236
			this.scribe.printIndentationIfNecessary();
2237
			this.scribe.scanner.resetTo(node.getStartPosition() + node.getLength(), this.scribe.scannerEndPosition);
2238
			this.scribe.needSpace = true;
2239
			this.scribe.printTrailingComment();
2240
			switch(this.scribe.scanner.source[this.scribe.scanner.currentPosition]) {
2241
				case '\n' :
2242
					this.scribe.scanner.currentPosition++;
2243
					this.scribe.lastNumberOfNewLines = 1;
2244
					break;
2245
				case '\r' :
2246
					this.scribe.scanner.currentPosition++;
2247
					if (this.scribe.scanner.source[this.scribe.scanner.currentPosition] == '\n') {
2248
						this.scribe.scanner.currentPosition++;
2249
					}
2250
					this.scribe.lastNumberOfNewLines = 1;
2251
			}
2252
			return false;
2253
		}
2254
        /*
2255
         * Print comments to get proper line number
2256
         */
2257
        this.scribe.printComment();
2258
        final int line = this.scribe.line;
2259
        
2260
        final List modifiers = node.modifiers();
2261
        final int modifiersLength = modifiers.size();
2262
        if (modifiersLength != 0) {
2263
        	this.scribe.printModifiers(modifiers, this);
2264
        	this.scribe.space();
2265
        }
2266
		
2267
        final List typeParameters = node.typeParameters();
2268
        final int typeParametersLength = typeParameters.size();
2269
		if (typeParametersLength != 0) {
2270
			this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters); 
2271
			if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
2272
				this.scribe.space();
2273
			}
2274
			for (int i = 0; i < typeParametersLength - 1; i++) {
2275
				((TypeParameter) typeParameters.get(i)).accept(this);
2276
				this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
2277
				if (this.preferences.insert_space_after_comma_in_type_parameters) {
2278
					this.scribe.space();
2279
				}				
2280
			}
2281
			((TypeParameter) typeParameters.get(typeParametersLength - 1)).accept(this);
2282
			if (isClosingGenericToken()) {
2283
				this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters); 
2284
			}
2285
			if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
2286
				this.scribe.space();
2287
			}
2288
		}
2289
		
2290
		final Type returnType = node.getReturnType2();
2291
		if (returnType != null) {
2292
			returnType.accept(this);
2293
		}
2294
		/*
2295
		 * Print the method name
2296
		 */
2297
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
2298
2299
		boolean spaceBeforeParen = this.preferences.insert_space_before_opening_paren_in_method_declaration;
2300
		if (node.isConstructor()) {
2301
			spaceBeforeParen = this.preferences.insert_space_before_opening_paren_in_constructor_declaration;
2302
		}
2303
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, spaceBeforeParen); 
2304
		
2305
		final List parameters = node.parameters();
2306
		final int parametersLength = parameters.size();
2307
		if (parametersLength != 0) {
2308
			if (this.preferences.insert_space_after_opening_paren_in_method_declaration) {
2309
				this.scribe.space();
2310
			}
2311
			Alignment2 parametersAlignment = this.scribe.createAlignment(
2312
					"methodParameters",//$NON-NLS-1$
2313
					this.preferences.alignment_for_parameters_in_method_declaration,
2314
					parametersLength,
2315
					this.scribe.scanner.currentPosition);
2316
			this.scribe.enterAlignment(parametersAlignment);
2317
			boolean ok = false;
2318
			do {
2319
				try {
2320
					for (int i = 0; i < parametersLength; i++) {
2321
						if (i > 0) {
2322
							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_declaration_parameters);
2323
							this.scribe.printTrailingComment();
2324
						}
2325
						this.scribe.alignFragment(parametersAlignment, i);
2326
						if (i > 0 && this.preferences.insert_space_after_comma_in_method_declaration_parameters) {
2327
							this.scribe.space();
2328
						}
2329
						((SingleVariableDeclaration) parameters.get(i)).accept(this);
2330
					}
2331
					ok = true;
2332
				} catch (AlignmentException e) {
2333
					this.scribe.redoAlignment(e);
2334
				}
2335
			} while (!ok);
2336
			this.scribe.exitAlignment(parametersAlignment, true);
2337
		
2338
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_declaration); 
2339
		} else {
2340
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_declaration); 
2341
		}
2342
		/*
2343
		 * Check for extra dimensions
2344
		 */
2345
		final int extraDimensions = node.getExtraDimensions();
2346
		if (extraDimensions != 0) {
2347
			 for (int i = 0; i < extraDimensions; i++) {
2348
			 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
2349
			 	this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
2350
			 }
2351
		}
2352
				
2353
		final List thrownExceptions = node.thrownExceptions();
2354
		final int thrownExceptionsLength = thrownExceptions.size();
2355
		if (thrownExceptionsLength != 0) {
2356
			Alignment2 throwsAlignment = this.scribe.createAlignment(
2357
					"throws",//$NON-NLS-1$
2358
					node.isConstructor()
2359
						? this.preferences.alignment_for_throws_clause_in_constructor_declaration
2360
						: this.preferences.alignment_for_throws_clause_in_method_declaration,
2361
					thrownExceptionsLength, // throws is the first token
2362
					this.scribe.scanner.currentPosition);
2363
		
2364
			this.scribe.enterAlignment(throwsAlignment);
2365
			boolean ok = false;
2366
			do {
2367
				try {
2368
					this.scribe.alignFragment(throwsAlignment, 0);
2369
					this.scribe.printNextToken(TerminalTokens.TokenNamethrows, true); 
2370
		
2371
					for (int i = 0; i < thrownExceptionsLength; i++) {
2372
						if (i > 0) {
2373
							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_declaration_throws);
2374
							this.scribe.printTrailingComment();
2375
							this.scribe.alignFragment(throwsAlignment, i);
2376
							if (this.preferences.insert_space_after_comma_in_method_declaration_throws) {
2377
								this.scribe.space();
2378
							}
2379
						} else {
2380
							this.scribe.space();
2381
						}
2382
						((Name) thrownExceptions.get(i)).accept(this);
2383
					}
2384
					ok = true;
2385
				} catch (AlignmentException e) {
2386
					this.scribe.redoAlignment(e);
2387
				}
2388
			} while (!ok);
2389
			this.scribe.exitAlignment(throwsAlignment, true);
2390
		}
2391
2392
		final Block body = node.getBody();
2393
		if (body != null) {
2394
			/*
2395
			 * Method body
2396
			 */
2397
			String method_declaration_brace = this.preferences.brace_position_for_method_declaration;
2398
            formatLeftCurlyBrace(line, method_declaration_brace);
2399
			formatOpeningBrace(method_declaration_brace, this.preferences.insert_space_before_opening_brace_in_method_declaration);
2400
			final int numberOfBlankLinesAtBeginningOfMethodBody = this.preferences.blank_lines_at_beginning_of_method_body;
2401
			if (numberOfBlankLinesAtBeginningOfMethodBody > 0) {
2402
				this.scribe.printEmptyLines(numberOfBlankLinesAtBeginningOfMethodBody);
2403
			}
2404
			final List statements = body.statements();
2405
			final int statementsLength = statements.size();
2406
			if (statementsLength != 0) {
2407
				this.scribe.printNewLine();
2408
				if (this.preferences.indent_statements_compare_to_body) {
2409
					this.scribe.indent();
2410
				}
2411
				formatStatements(statements, true);
2412
				this.scribe.printComment();
2413
				if (this.preferences.indent_statements_compare_to_body) {
2414
					this.scribe.unIndent();
2415
				}
2416
			} else if (this.preferences.insert_new_line_in_empty_method_body) {
2417
				this.scribe.printNewLine();
2418
				if (this.preferences.indent_statements_compare_to_body) {
2419
					this.scribe.indent();
2420
				}
2421
				this.scribe.printComment();
2422
				if (this.preferences.indent_statements_compare_to_body) {
2423
					this.scribe.unIndent();
2424
				}
2425
			}
2426
			this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
2427
			this.scribe.printTrailingComment();
2428
			if (method_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
2429
				this.scribe.unIndent();
2430
			}
2431
		} else {
2432
			// no method body
2433
			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2434
			this.scribe.printTrailingComment();
2435
		}
2436
		return false;
2437
	}
2438
2439
	public boolean visit(MethodInvocation node) {
2440
		MethodInvocationFragmentBuilder builder = new MethodInvocationFragmentBuilder();
2441
		node.accept(builder);
2442
		
2443
		final List fragments = builder.fragments();
2444
		final int fragmentsLength = fragments.size();
2445
		if (fragmentsLength >= 3) {
2446
			// manage cascading method invocations
2447
			// check the first fragment
2448
			final Expression firstFragment = (Expression) fragments.get(0);
2449
			switch(firstFragment.getNodeType()) {
2450
				case ASTNode.METHOD_INVOCATION :
2451
					formatSingleMethodInvocation((MethodInvocation) firstFragment);
2452
					break;
2453
				default:
2454
					firstFragment.accept(this);
2455
			}
2456
			Alignment2 cascadingMessageSendAlignment =
2457
				this.scribe.createAlignment(
2458
					"cascadingMessageSendAlignment", //$NON-NLS-1$
2459
					this.preferences.alignment_for_selector_in_method_invocation,
2460
					Alignment.R_INNERMOST,
2461
					fragmentsLength,
2462
					this.scribe.scanner.currentPosition);
2463
			this.scribe.enterAlignment(cascadingMessageSendAlignment);
2464
			boolean ok = false;
2465
			do {
2466
				try {
2467
					this.scribe.alignFragment(cascadingMessageSendAlignment, 0);
2468
					this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2469
					for (int i = 1; i < fragmentsLength - 1; i++) {
2470
						MethodInvocation  currentMethodInvocation = (MethodInvocation) fragments.get(i);
2471
						formatSingleMethodInvocation(currentMethodInvocation);
2472
						this.scribe.alignFragment(cascadingMessageSendAlignment, i);
2473
						this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2474
					}
2475
					MethodInvocation  currentMethodInvocation = (MethodInvocation) fragments.get(fragmentsLength - 1);
2476
					formatSingleMethodInvocation(currentMethodInvocation);
2477
					ok = true;
2478
				} catch(AlignmentException e){
2479
					this.scribe.redoAlignment(e);
2480
				}
2481
			} while (!ok);		
2482
			this.scribe.exitAlignment(cascadingMessageSendAlignment, true);
2483
		} else {
2484
			Expression expression = node.getExpression();
2485
			if (expression != null) {
2486
				expression.accept(this);
2487
				this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2488
			}
2489
			formatSingleMethodInvocation(node);			
2490
		}
2491
		return false;
2492
	}
2493
2494
	private void formatSingleMethodInvocation(MethodInvocation node) {
2495
		final List typeArguments = node.typeArguments();
2496
		final int typeArgumentsLength = typeArguments.size();
2497
		if (typeArgumentsLength != 0) {
2498
			this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments); 
2499
			if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
2500
				this.scribe.space();
2501
			}
2502
			for (int i = 0; i < typeArgumentsLength - 1; i++) {
2503
				((Type) typeArguments.get(i)).accept(this);
2504
				this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
2505
				if (this.preferences.insert_space_after_comma_in_type_arguments) {
2506
					this.scribe.space();
2507
				}				
2508
			}
2509
			((Type) typeArguments.get(typeArgumentsLength - 1)).accept(this);
2510
			if (isClosingGenericToken()) {
2511
				this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments); 
2512
			}
2513
			if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
2514
				this.scribe.space();
2515
			}
2516
		}
2517
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
2518
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
2519
2520
		final List arguments = node.arguments();
2521
		final int argumentsLength = arguments.size();
2522
		if (argumentsLength != 0) {
2523
			if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
2524
				this.scribe.space();
2525
			}
2526
			if (argumentsLength > 1) {
2527
				Alignment2 argumentsAlignment = this.scribe.createAlignment(
2528
						"messageArguments", //$NON-NLS-1$
2529
						this.preferences.alignment_for_arguments_in_method_invocation,
2530
						argumentsLength,
2531
						this.scribe.scanner.currentPosition);
2532
				this.scribe.enterAlignment(argumentsAlignment);
2533
				boolean ok = false;
2534
				do {
2535
					try {
2536
						for (int i = 0; i < argumentsLength; i++) {
2537
							if (i > 0) {
2538
								this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
2539
								this.scribe.printTrailingComment();
2540
							}
2541
							this.scribe.alignFragment(argumentsAlignment, i);
2542
							if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
2543
								this.scribe.space();
2544
							}
2545
							((Expression) arguments.get(i)).accept(this);
2546
						}
2547
						ok = true;
2548
					} catch (AlignmentException e) {
2549
						this.scribe.redoAlignment(e);
2550
					}
2551
				} while (!ok);
2552
				this.scribe.exitAlignment(argumentsAlignment, true);
2553
			} else {
2554
				for (int i = 0; i < argumentsLength; i++) {
2555
					if (i > 0) {
2556
						this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
2557
						this.scribe.printTrailingComment();
2558
					}
2559
					if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
2560
						this.scribe.space();
2561
					}
2562
					((Expression) arguments.get(i)).accept(this);
2563
				}
2564
			}
2565
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation); 
2566
		} else {
2567
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
2568
		}
2569
	}
2570
	
2571
	public boolean visit(NormalAnnotation node) {
2572
		this.scribe.printNextToken(TerminalTokens.TokenNameAT);
2573
		if (this.preferences.insert_space_after_at_in_annotation) {
2574
			this.scribe.space();
2575
		}
2576
		node.getTypeName().accept(this);
2577
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
2578
		if (this.preferences.insert_space_after_opening_paren_in_annotation) {
2579
			this.scribe.space();
2580
		}
2581
		final List memberValuePairs = node.values();
2582
		final int memberValuePairsLength = memberValuePairs.size();
2583
		if (memberValuePairs.size() != 0) {
2584
			for (int i = 0; i < memberValuePairsLength - 1; i++) {
2585
				((MemberValuePair) memberValuePairs.get(i)).accept(this);
2586
				this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_annotation);
2587
				if (this.preferences.insert_space_after_comma_in_annotation) {
2588
					this.scribe.space();
2589
				}
2590
			}
2591
			((MemberValuePair) memberValuePairs.get(memberValuePairsLength - 1)).accept(this);
2592
		}
2593
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
2594
		return false;
2595
	}
2596
2597
	public boolean visit(NullLiteral node) {
2598
		this.scribe.printNextToken(TerminalTokens.TokenNamenull);
2599
		return false;
2600
	}
2601
2602
	public boolean visit(NumberLiteral node) {
2603
		if (isNextToken(TerminalTokens.TokenNameMINUS)) {
2604
			this.scribe.printNextToken(TerminalTokens.TokenNameMINUS, this.preferences.insert_space_before_unary_operator);
2605
			if (this.preferences.insert_space_after_unary_operator) {
2606
				this.scribe.space();
2607
			}
2608
		}
2609
		this.scribe.printNextToken(NUMBER_LITERALS_EXPECTEDTOKENS); 
2610
		return false;
2611
	}
2612
2613
	public boolean visit(ParameterizedType node) {
2614
		node.getType().accept(this);
2615
		this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
2616
		if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
2617
			this.scribe.space();
2618
		}
2619
		final List typeArguments = node.typeArguments();
2620
		final int typeArgumentsLength = typeArguments.size();
2621
		for (int i = 0; i < typeArgumentsLength - 1; i++) {
2622
			((Type) typeArguments.get(i)).accept(this);
2623
			this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
2624
			if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
2625
				this.scribe.space();
2626
			}			
2627
		}
2628
		((Type) typeArguments.get(typeArgumentsLength - 1)).accept(this);
2629
		if (isClosingGenericToken()) {
2630
			this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
2631
		}
2632
		return false;
2633
	}
2634
2635
	public boolean visit(ParenthesizedExpression node) {
2636
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_parenthesized_expression);
2637
		if (this.preferences.insert_space_after_opening_paren_in_parenthesized_expression) {
2638
			this.scribe.space();
2639
		}
2640
		node.getExpression().accept(this);
2641
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_parenthesized_expression);
2642
		return false;
2643
	}
2644
2645
	public boolean visit(PostfixExpression node) {
2646
		node.getOperand().accept(this);
2647
		int operator = node.getOperator() == PostfixExpression.Operator.INCREMENT
2648
			? TerminalTokens.TokenNamePLUS_PLUS : TerminalTokens.TokenNameMINUS_MINUS;
2649
		this.scribe.printNextToken(operator, this.preferences.insert_space_before_postfix_operator);
2650
		if (this.preferences.insert_space_after_postfix_operator) {
2651
			this.scribe.space();
2652
		}
2653
		return false;
2654
	}
2655
2656
	public boolean visit(PrefixExpression node) {
2657
		int operator;
2658
		boolean insertSpaceBeforeOperator;
2659
		boolean insertSpaceAfterOperator;
2660
		final Operator operator2 = node.getOperator();
2661
		if (operator2 == PrefixExpression.Operator.INCREMENT) {
2662
			operator = TerminalTokens.TokenNamePLUS_PLUS;
2663
			insertSpaceBeforeOperator = this.preferences.insert_space_before_prefix_operator;
2664
			insertSpaceAfterOperator = this.preferences.insert_space_after_prefix_operator;
2665
		} else if (operator2 == PrefixExpression.Operator.DECREMENT) {
2666
			operator = TerminalTokens.TokenNameMINUS_MINUS;
2667
			insertSpaceBeforeOperator = this.preferences.insert_space_before_prefix_operator;
2668
			insertSpaceAfterOperator = this.preferences.insert_space_after_prefix_operator;
2669
		} else if (operator2 == PrefixExpression.Operator.COMPLEMENT) {
2670
			operator = TerminalTokens.TokenNameTWIDDLE;
2671
			insertSpaceBeforeOperator = this.preferences.insert_space_before_unary_operator;
2672
			insertSpaceAfterOperator = this.preferences.insert_space_after_unary_operator;
2673
		} else if (operator2 == PrefixExpression.Operator.MINUS) {
2674
			operator = TerminalTokens.TokenNameMINUS;
2675
			insertSpaceBeforeOperator = this.preferences.insert_space_before_unary_operator;
2676
			insertSpaceAfterOperator = this.preferences.insert_space_after_unary_operator;
2677
		} else if (operator2 == PrefixExpression.Operator.NOT) {
2678
			operator = TerminalTokens.TokenNameNOT;
2679
			insertSpaceBeforeOperator = this.preferences.insert_space_before_unary_operator;
2680
			insertSpaceAfterOperator = this.preferences.insert_space_after_unary_operator;
2681
		} else {
2682
			operator = TerminalTokens.TokenNamePLUS;
2683
			insertSpaceBeforeOperator = this.preferences.insert_space_before_unary_operator;
2684
			insertSpaceAfterOperator = this.preferences.insert_space_after_unary_operator;
2685
		}
2686
2687
		this.scribe.printNextToken(operator, insertSpaceBeforeOperator);
2688
		if (insertSpaceAfterOperator) {
2689
			this.scribe.space();
2690
		}
2691
		node.getOperand().accept(this);
2692
		return false;
2693
	}
2694
2695
	public boolean visit(PrimitiveType node) {
2696
		this.scribe.printNextToken(PRIMITIVE_TYPE_EXPECTEDTOKENS);
2697
		return false;
2698
	}
2699
2700
	public boolean visit(QualifiedName node) {
2701
		node.getQualifier().accept(this);
2702
		this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2703
		node.getName().accept(this);
2704
		return false;
2705
	}
2706
2707
	public boolean visit(QualifiedType node) {
2708
		node.getQualifier().accept(this);
2709
		this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2710
		node.getName().accept(this);
2711
		return false;
2712
	}
2713
2714
	public boolean visit(ReturnStatement node) {
2715
		this.scribe.printNextToken(TerminalTokens.TokenNamereturn);
2716
		final Expression expression = node.getExpression();
2717
		if (expression != null) {
2718
			switch(expression.getNodeType()) {
2719
				case ASTNode.PARENTHESIZED_EXPRESSION :
2720
					if (this.preferences.insert_space_before_parenthesized_expression_in_return) {
2721
						this.scribe.space();
2722
					}
2723
					break;
2724
				default:
2725
					this.scribe.space();
2726
			}
2727
			expression.accept(this);
2728
		}
2729
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2730
		this.scribe.printTrailingComment();
2731
		return false;
2732
	}
2733
2734
	public boolean visit(SimpleName node) {
2735
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
2736
		return false;
2737
	}
2738
2739
	public boolean visit(SimpleType node) {
2740
		node.getName().accept(this);
2741
		return false;
2742
	}
2743
2744
	public boolean visit(SingleMemberAnnotation node) {
2745
		this.scribe.printNextToken(TerminalTokens.TokenNameAT);
2746
		if (this.preferences.insert_space_after_at_in_annotation) {
2747
			this.scribe.space();
2748
		}
2749
		node.getTypeName().accept(this);
2750
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
2751
		if (this.preferences.insert_space_after_opening_paren_in_annotation) {
2752
			this.scribe.space();
2753
		}
2754
		node.getValue().accept(this);
2755
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
2756
		return false;
2757
	}
2758
2759
	public boolean visit(SingleVariableDeclaration node) {
2760
		final List modifiers = node.modifiers();
2761
		if (modifiers.size() != 0) {
2762
			this.scribe.printModifiers(modifiers, this);
2763
			this.scribe.space();
2764
		}
2765
2766
		node.getType().accept(this);
2767
		
2768
		if (node.isVarargs()) {
2769
			this.scribe.printNextToken(TerminalTokens.TokenNameELLIPSIS, this.preferences.insert_space_before_ellipsis);
2770
			if (this.preferences.insert_space_after_ellipsis) {
2771
				this.scribe.space();
2772
			}
2773
			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
2774
		} else {
2775
			/*
2776
			 * Print the argument name
2777
			 */	
2778
			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
2779
		}
2780
		
2781
		final int extraDimensions = node.getExtraDimensions();
2782
		if (extraDimensions != 0) {
2783
			for (int i = 0; i < extraDimensions; i++) {
2784
				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
2785
				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
2786
			}
2787
		}
2788
		final Expression initialization = node.getInitializer();
2789
		if (initialization != null) {
2790
			this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
2791
			if (this.preferences.insert_space_after_assignment_operator) {
2792
				this.scribe.space();
2793
			}
2794
			Alignment2 assignmentAlignment = this.scribe.createAlignment("localDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
2795
			this.scribe.enterAlignment(assignmentAlignment);
2796
			boolean ok = false;
2797
			do {
2798
				try {
2799
					this.scribe.alignFragment(assignmentAlignment, 0);
2800
					initialization.accept(this);
2801
					ok = true;
2802
				} catch(AlignmentException e){
2803
					this.scribe.redoAlignment(e);
2804
				}
2805
			} while (!ok);		
2806
			this.scribe.exitAlignment(assignmentAlignment, true);			
2807
		}
2808
		return false;
2809
	}
2810
2811
	public boolean visit(StringLiteral node) {
2812
		this.scribe.checkNLSTag(node.getStartPosition());
2813
		this.scribe.printNextToken(TerminalTokens.TokenNameStringLiteral);
2814
		this.scribe.printTrailingComment();
2815
		return false;
2816
	}
2817
2818
	public boolean visit(SuperConstructorInvocation node) {
2819
		final Expression qualification = node.getExpression();
2820
		if (qualification != null) {
2821
			qualification.accept(this);
2822
			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2823
		}
2824
		final List typeArguments = node.typeArguments();
2825
		final int typeArgumentsLength = typeArguments.size();
2826
		if (typeArgumentsLength != 0) {
2827
				this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments); 
2828
				if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
2829
					this.scribe.space();
2830
				}
2831
				for (int i = 0; i < typeArgumentsLength - 1; i++) {
2832
					((Type) typeArguments.get(i)).accept(this);
2833
					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
2834
					if (this.preferences.insert_space_after_comma_in_type_arguments) {
2835
						this.scribe.space();
2836
					}				
2837
				}
2838
				((Type) typeArguments.get(typeArgumentsLength - 1)).accept(this);
2839
				if (isClosingGenericToken()) {
2840
					this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments); 
2841
				}
2842
				if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
2843
					this.scribe.space();
2844
				}
2845
		}
2846
		
2847
		this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
2848
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
2849
		
2850
		final List arguments = node.arguments();
2851
		final int argumentsLength = arguments.size();
2852
		if (argumentsLength != 0) {
2853
			if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
2854
				this.scribe.space();
2855
			}
2856
			Alignment2 argumentsAlignment =this.scribe.createAlignment(
2857
					"explicit_constructor_call",//$NON-NLS-1$
2858
					this.preferences.alignment_for_arguments_in_explicit_constructor_call,
2859
					argumentsLength,
2860
					this.scribe.scanner.currentPosition);
2861
			this.scribe.enterAlignment(argumentsAlignment);
2862
			boolean ok = false;
2863
			do {
2864
				try {
2865
					for (int i = 0; i < argumentsLength; i++) {
2866
						if (i > 0) {
2867
							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_explicit_constructor_call_arguments);
2868
							this.scribe.printTrailingComment();
2869
						}
2870
						this.scribe.alignFragment(argumentsAlignment, i);
2871
						if (i > 0 && this.preferences.insert_space_after_comma_in_explicit_constructor_call_arguments) {
2872
							this.scribe.space();
2873
						}
2874
						((Expression) arguments.get(i)).accept(this);
2875
					}
2876
					ok = true;
2877
				} catch (AlignmentException e) {
2878
					this.scribe.redoAlignment(e);
2879
				}
2880
			} while (!ok);
2881
			this.scribe.exitAlignment(argumentsAlignment, true);
2882
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation); 
2883
		} else {
2884
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation); 
2885
		}
2886
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2887
		this.scribe.printTrailingComment();
2888
		return false;
2889
	}
2890
2891
	public boolean visit(SuperFieldAccess node) {
2892
		final Name qualifier = node.getQualifier();
2893
		if (qualifier != null) {
2894
			qualifier.accept(this);
2895
			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2896
		}
2897
		this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
2898
		this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2899
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
2900
		return false;
2901
	}
2902
2903
	public boolean visit(SuperMethodInvocation node) {
2904
		final Name qualifier = node.getQualifier();
2905
		if (qualifier != null) {
2906
			qualifier.accept(this);
2907
			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2908
		}
2909
		this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
2910
		this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2911
		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
2912
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
2913
2914
		final List arguments = node.arguments();
2915
		final int argumentsLength = arguments.size();
2916
		if (argumentsLength != 0) {
2917
			if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
2918
				this.scribe.space();
2919
			}
2920
			if (argumentsLength > 1) {
2921
				Alignment2 argumentsAlignment = this.scribe.createAlignment(
2922
						"messageArguments", //$NON-NLS-1$
2923
						this.preferences.alignment_for_arguments_in_method_invocation,
2924
						argumentsLength,
2925
						this.scribe.scanner.currentPosition);
2926
				this.scribe.enterAlignment(argumentsAlignment);
2927
				boolean ok = false;
2928
				do {
2929
					try {
2930
						for (int i = 0; i < argumentsLength; i++) {
2931
							if (i > 0) {
2932
								this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
2933
								this.scribe.printTrailingComment();
2934
							}
2935
							this.scribe.alignFragment(argumentsAlignment, i);
2936
							if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
2937
								this.scribe.space();
2938
							}
2939
							((Expression) arguments.get(i)).accept(this);
2940
						}
2941
						ok = true;
2942
					} catch (AlignmentException e) {
2943
						this.scribe.redoAlignment(e);
2944
					}
2945
				} while (!ok);
2946
				this.scribe.exitAlignment(argumentsAlignment, true);
2947
			} else {
2948
				for (int i = 0; i < argumentsLength; i++) {
2949
					if (i > 0) {
2950
						this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
2951
						this.scribe.printTrailingComment();
2952
					}
2953
					if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
2954
						this.scribe.space();
2955
					}
2956
					((Expression) arguments.get(i)).accept(this);
2957
				}
2958
			}
2959
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation); 
2960
		} else {
2961
			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
2962
		}			
2963
		return false;
2964
	}
2965
2966
	public boolean visit(SwitchCase node) {
2967
		Expression constant = node.getExpression();
2968
		if (constant == null) {
2969
			this.scribe.printNextToken(TerminalTokens.TokenNamedefault);
2970
			this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_default);
2971
		} else {
2972
			this.scribe.printNextToken(TerminalTokens.TokenNamecase);
2973
			this.scribe.space();
2974
			constant.accept(this);
2975
			this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_case);
2976
		}
2977
		return false;
2978
	}
2979
2980
	public boolean visit(SwitchStatement node) {
2981
		this.scribe.printNextToken(TerminalTokens.TokenNameswitch);
2982
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_switch);
2983
		
2984
		if (this.preferences.insert_space_after_opening_paren_in_switch) {
2985
			this.scribe.space();
2986
		}
2987
		
2988
		node.getExpression().accept(this);
2989
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_switch);
2990
		/*
2991
		 * Type body
2992
		 */
2993
		String switch_brace = this.preferences.brace_position_for_switch;
2994
		formatOpeningBrace(switch_brace, this.preferences.insert_space_before_opening_brace_in_switch);
2995
		this.scribe.printNewLine();
2996
2997
		if (this.preferences.indent_switchstatements_compare_to_switch) {
2998
			this.scribe.indent();
2999
		}
3000
		final List statements = node.statements();
3001
		final int statementsLength = statements.size();
3002
		boolean wasACase = false;
3003
		boolean wasAStatement = false;
3004
		if (statementsLength != 0) {
3005
			for (int i = 0; i < statementsLength; i++) {
3006
				final Statement statement = (Statement) statements.get(i);
3007
				if (statement instanceof SwitchCase) {
3008
					if (wasACase) {
3009
						this.scribe.printNewLine();
3010
					}
3011
					if ((wasACase && this.preferences.indent_switchstatements_compare_to_cases) 
3012
						|| (wasAStatement && this.preferences.indent_switchstatements_compare_to_cases)) {
3013
						this.scribe.unIndent();
3014
					}
3015
					statement.accept(this);
3016
					this.scribe.printTrailingComment();
3017
					wasACase = true;
3018
					wasAStatement = false;
3019
					if (this.preferences.indent_switchstatements_compare_to_cases) {
3020
						this.scribe.indent();
3021
					}
3022
				} else if (statement instanceof BreakStatement) {
3023
					if (this.preferences.indent_breaks_compare_to_cases) {
3024
						if (wasAStatement && !this.preferences.indent_switchstatements_compare_to_cases) {
3025
							this.scribe.indent();
3026
						}
3027
					} else {
3028
						if (wasAStatement) {
3029
							if (this.preferences.indent_switchstatements_compare_to_cases) {
3030
								this.scribe.unIndent();
3031
							}
3032
						}
3033
						if (wasACase && this.preferences.indent_switchstatements_compare_to_cases) {
3034
							this.scribe.unIndent();
3035
						}
3036
					}
3037
					if (wasACase) {
3038
						this.scribe.printNewLine();
3039
					}
3040
					statement.accept(this);
3041
					if (this.preferences.indent_breaks_compare_to_cases) {
3042
						this.scribe.unIndent();
3043
					}
3044
					wasACase = false;
3045
					wasAStatement = false;
3046
				} else if (statement instanceof Block) {
3047
					String bracePosition;
3048
					if (wasACase) {
3049
						if (this.preferences.indent_switchstatements_compare_to_cases) {
3050
							this.scribe.unIndent();
3051
						}
3052
						bracePosition =	this.preferences.brace_position_for_block_in_case;
3053
						formatBlock((Block) statement, bracePosition, this.preferences.insert_space_after_colon_in_case);
3054
						if (this.preferences.indent_switchstatements_compare_to_cases) {
3055
							this.scribe.indent();
3056
						}
3057
					} else {
3058
						bracePosition =	this.preferences.brace_position_for_block;
3059
						formatBlock((Block) statement, bracePosition, this.preferences.insert_space_before_opening_brace_in_block);
3060
					}
3061
					wasAStatement = true;
3062
					wasACase = false;
3063
				} else {
3064
					this.scribe.printNewLine();
3065
					statement.accept(this);
3066
					wasAStatement = true;
3067
					wasACase = false;
3068
				}
3069
				if (!wasACase) {
3070
					this.scribe.printNewLine();
3071
				}
3072
				this.scribe.printComment();
3073
			}
3074
		}		
3075
		
3076
		if ((wasACase || wasAStatement) && this.preferences.indent_switchstatements_compare_to_cases) {
3077
			this.scribe.unIndent();
3078
		}
3079
		if (this.preferences.indent_switchstatements_compare_to_switch) {
3080
			this.scribe.unIndent();
3081
		}
3082
		this.scribe.printNewLine();
3083
		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
3084
		this.scribe.printTrailingComment();
3085
		if (switch_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
3086
			this.scribe.unIndent();
3087
		}		
3088
		return false;
3089
	}
3090
3091
	public boolean visit(SynchronizedStatement node) {
3092
		this.scribe.printNextToken(TerminalTokens.TokenNamesynchronized);
3093
3094
		final int line = this.scribe.line;
3095
3096
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_synchronized);
3097
		
3098
		if (this.preferences.insert_space_after_opening_paren_in_synchronized) {
3099
			this.scribe.space();
3100
		}
3101
		node.getExpression().accept(this);
3102
	
3103
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_synchronized);
3104
		
3105
		formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
3106
		node.getBody().accept(this);
3107
		return false;
3108
	}
3109
3110
	public boolean visit(ThisExpression node) {
3111
		final Name qualifier = node.getQualifier();
3112
		if (qualifier != null) {
3113
			qualifier.accept(this);
3114
			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
3115
		}
3116
		this.scribe.printNextToken(TerminalTokens.TokenNamethis);
3117
		return false;
3118
	}
3119
3120
	public boolean visit(ThrowStatement node) {
3121
		this.scribe.printNextToken(TerminalTokens.TokenNamethrow);
3122
		this.scribe.space();
3123
		node.getExpression().accept(this);
3124
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3125
		this.scribe.printTrailingComment();
3126
		return false;
3127
	}
3128
3129
	public boolean visit(TryStatement node) {
3130
3131
		this.scribe.printNextToken(TerminalTokens.TokenNametry);
3132
		node.getBody().accept(this);
3133
		final List catchClauses = node.catchClauses();
3134
		final int catchClausesLength = catchClauses.size();
3135
		if (catchClausesLength != 0) {
3136
			for (int i = 0; i < catchClausesLength; i++) {
3137
				if (this.preferences.insert_new_line_before_catch_in_try_statement) {
3138
					this.scribe.printNewLine();
3139
				}	
3140
				this.scribe.printNextToken(TerminalTokens.TokenNamecatch, this.preferences.insert_space_after_closing_brace_in_block);
3141
				final int line = this.scribe.line;
3142
				this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_catch);
3143
				
3144
				if (this.preferences.insert_space_after_opening_paren_in_catch) {
3145
					this.scribe.space();
3146
				}
3147
				
3148
				final CatchClause catchClause = ((CatchClause) catchClauses.get(i));
3149
				catchClause.getException().accept(this);
3150
			
3151
				this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_catch);
3152
				
3153
				formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
3154
				catchClause.getBody().accept(this);
3155
			}
3156
		}
3157
		final Block finallyBlock = node.getFinally();
3158
		if (finallyBlock != null) {
3159
			if (this.preferences.insert_new_line_before_finally_in_try_statement) {
3160
				this.scribe.printNewLine();
3161
			}	
3162
			this.scribe.printNextToken(TerminalTokens.TokenNamefinally, this.preferences.insert_space_after_closing_brace_in_block);
3163
			finallyBlock.accept(this);
3164
		}
3165
		return false;
3166
	}
3167
3168
	public boolean visit(TypeDeclaration node) {
3169
        /*
3170
         * Print comments to get proper line number
3171
         */
3172
        this.scribe.printComment();
3173
        final int line = this.scribe.line; 
3174
        
3175
        final List modifiers = node.modifiers();
3176
        if (modifiers.size() != 0) {
3177
            this.scribe.printModifiers(modifiers, this);
3178
            this.scribe.space();
3179
        }
3180
        final boolean isInterface = node.isInterface();
3181
		if (isInterface) {
3182
			this.scribe.printNextToken(TerminalTokens.TokenNameinterface, true);
3183
        } else {
3184
			this.scribe.printNextToken(TerminalTokens.TokenNameclass, true);
3185
        }
3186
3187
        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
3188
3189
        final List typeParameters = node.typeParameters();
3190
        final int typeParametersLength = typeParameters.size();
3191
		if (typeParametersLength != 0) {
3192
			this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters); 
3193
			if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
3194
				this.scribe.space();
3195
			}
3196
			for (int i = 0; i < typeParametersLength - 1; i++) {
3197
				((TypeParameter) typeParameters.get(i)).accept(this);
3198
				this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
3199
				if (this.preferences.insert_space_after_comma_in_type_parameters) {
3200
					this.scribe.space();
3201
				}				
3202
			}
3203
			((TypeParameter) typeParameters.get(typeParametersLength - 1)).accept(this);
3204
			if (isClosingGenericToken()) {
3205
				this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters); 
3206
			}
3207
			if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
3208
				this.scribe.space();
3209
			}
3210
		}
3211
		/* 
3212
		 * Superclass 
3213
		 */
3214
		final Type superclass = node.getSuperclassType();
3215
		if (superclass != null) {
3216
			Alignment2 superclassAlignment =this.scribe.createAlignment(
3217
					"superclass", //$NON-NLS-1$
3218
					this.preferences.alignment_for_superclass_in_type_declaration,
3219
					2,
3220
					this.scribe.scanner.currentPosition);
3221
			this.scribe.enterAlignment(superclassAlignment);
3222
			boolean ok = false;
3223
			do {
3224
				try {
3225
					this.scribe.alignFragment(superclassAlignment, 0);
3226
					this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
3227
					this.scribe.alignFragment(superclassAlignment, 1);
3228
					this.scribe.space();
3229
					superclass.accept(this);
3230
					ok = true;
3231
				} catch (AlignmentException e) {
3232
					this.scribe.redoAlignment(e);
3233
				}
3234
			} while (!ok);
3235
			this.scribe.exitAlignment(superclassAlignment, true); 
3236
		}
3237
3238
		/* 
3239
		 * Super Interfaces 
3240
		 */
3241
		final List superInterfaces = node.superInterfaceTypes();
3242
		final int superInterfacesLength = superInterfaces.size();
3243
		if (superInterfacesLength != 0) {
3244
			Alignment2 interfaceAlignment = this.scribe.createAlignment(
3245
					"superInterfaces",//$NON-NLS-1$
3246
					this.preferences.alignment_for_superinterfaces_in_type_declaration,
3247
					superInterfacesLength+1,  // implements token is first fragment
3248
					this.scribe.scanner.currentPosition);
3249
			this.scribe.enterAlignment(interfaceAlignment);
3250
			boolean ok = false;
3251
			do {
3252
				try {
3253
					this.scribe.alignFragment(interfaceAlignment, 0);
3254
					if (isInterface) {
3255
						this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
3256
					} else {
3257
						this.scribe.printNextToken(TerminalTokens.TokenNameimplements, true);
3258
					}
3259
					this.scribe.alignFragment(interfaceAlignment, 1);
3260
					this.scribe.space();
3261
					((Type) superInterfaces.get(0)).accept(this);
3262
					for (int i = 1; i < superInterfacesLength; i++) {
3263
						this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_superinterfaces);
3264
						this.scribe.printTrailingComment();
3265
						this.scribe.alignFragment(interfaceAlignment, i+1);
3266
						if (this.preferences.insert_space_after_comma_in_superinterfaces) {
3267
							this.scribe.space();
3268
						}
3269
						((Type) superInterfaces.get(i)).accept(this);
3270
					}
3271
					ok = true;
3272
				} catch (AlignmentException e) {
3273
					this.scribe.redoAlignment(e);
3274
				}
3275
			} while (!ok);
3276
			this.scribe.exitAlignment(interfaceAlignment, true);
3277
		}
3278
3279
		final String class_declaration_brace = this.preferences.brace_position_for_type_declaration;
3280
		final boolean space_before_opening_brace = this.preferences.insert_space_before_opening_brace_in_type_declaration;
3281
3282
		formatLeftCurlyBrace(line, class_declaration_brace);
3283
		final List bodyDeclarations = node.bodyDeclarations();
3284
		formatTypeOpeningBrace(class_declaration_brace, space_before_opening_brace, bodyDeclarations.size() != 0, node);
3285
		
3286
		final boolean indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_type_header;
3287
3288
		if (indent_body_declarations_compare_to_header) {
3289
			this.scribe.indent();
3290
		}
3291
		
3292
		formatTypeMembers(bodyDeclarations, true);
3293
		
3294
		if (indent_body_declarations_compare_to_header) {
3295
			this.scribe.unIndent();
3296
		}
3297
3298
		if (this.preferences.insert_new_line_in_empty_type_declaration) {
3299
			this.scribe.printNewLine();
3300
		}
3301
		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
3302
		this.scribe.printTrailingComment();
3303
		if (class_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
3304
			this.scribe.unIndent();
3305
		}
3306
		if (hasComments()) {
3307
			this.scribe.printNewLine();
3308
		}
3309
		return false;
3310
	}
3311
3312
	public boolean visit(TypeDeclarationStatement node) {
3313
		node.getDeclaration().accept(this);
3314
		return false;
3315
	}
3316
3317
	public boolean visit(TypeLiteral node) {
3318
		node.getType().accept(this);
3319
		this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
3320
		this.scribe.printNextToken(TerminalTokens.TokenNameclass);
3321
		return false;
3322
	}
3323
3324
	public boolean visit(TypeParameter node) {
3325
		node.getName().accept(this);
3326
		final List bounds = node.typeBounds();
3327
		final int boundsLength = bounds.size();
3328
		if (boundsLength != 0) {
3329
			this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
3330
			this.scribe.space();
3331
			((Type) bounds.get(0)).accept(this);
3332
			if (boundsLength > 1) {
3333
				this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
3334
				if (this.preferences.insert_space_after_and_in_type_parameter) {
3335
					this.scribe.space();
3336
				}
3337
				for (int i = 1; i < boundsLength - 1; i++) {
3338
					((Type) bounds.get(i)).accept(this);
3339
					this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
3340
					if (this.preferences.insert_space_after_and_in_type_parameter) {
3341
						this.scribe.space();
3342
					}
3343
				}
3344
				((Type) bounds.get(boundsLength - 1)).accept(this);
3345
			}
3346
		}
3347
		return false;
3348
	}
3349
3350
	public boolean visit(VariableDeclarationExpression node) {
3351
		formatLocalDeclaration(node, this.preferences.insert_space_before_comma_in_multiple_local_declarations, this.preferences.insert_space_after_comma_in_multiple_local_declarations);
3352
		return false;
3353
	}
3354
3355
	public boolean visit(VariableDeclarationStatement node) {
3356
		final List modifiers = node.modifiers();
3357
		if (modifiers.size() != 0) {
3358
			this.scribe.printModifiers(modifiers, this);
3359
			this.scribe.space();
3360
		}
3361
3362
		node.getType().accept(this);
3363
		
3364
		formatVariableDeclarationFragments(node.fragments(), this.preferences.insert_space_before_comma_in_multiple_local_declarations, this.preferences.insert_space_after_comma_in_multiple_local_declarations);
3365
		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3366
		this.scribe.printTrailingComment();
3367
		return false;
3368
	}
3369
3370
	public boolean visit(WhileStatement node) {
3371
		this.scribe.printNextToken(TerminalTokens.TokenNamewhile);
3372
		final int line = this.scribe.line;
3373
		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_while);
3374
		
3375
		if (this.preferences.insert_space_after_opening_paren_in_while) {
3376
			this.scribe.space();
3377
		}
3378
		node.getExpression().accept(this);
3379
		
3380
		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_while);
3381
		
3382
		formatAction(line, node.getBody(),false);
3383
		return false;
3384
	}
3385
3386
	public boolean visit(WildcardType node) {
3387
		this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_wilcard);
3388
		final Type bound = node.getBound();
3389
		if (bound != null) {
3390
			if (node.isUpperBound()) {
3391
				this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);				
3392
			} else {
3393
				this.scribe.printNextToken(TerminalTokens.TokenNamesuper, true);				
3394
			}
3395
			this.scribe.space();
3396
			bound.accept(this);
3397
		} else if (this.preferences.insert_space_after_question_in_wilcard) {
3398
			this.scribe.space();
3399
		}
3400
		return false;
3401
	}
3402
	
3403
}
(-)formatter/org/eclipse/jdt/internal/formatter/InfixExpressionWrappingBuilder.java (-86 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.formatter;
12
13
import java.util.ArrayList;
14
import java.util.List;
15
16
import org.eclipse.jdt.core.dom.ASTNode;
17
import org.eclipse.jdt.core.dom.ASTVisitor;
18
import org.eclipse.jdt.core.dom.Expression;
19
import org.eclipse.jdt.core.dom.InfixExpression;
20
21
public class InfixExpressionWrappingBuilder extends ASTVisitor {
22
	private final static int DEFAULT_SIZE = 10;
23
	ArrayList fragments = new ArrayList();
24
	int[] operators = new int[DEFAULT_SIZE];
25
	int operatorCounter = 0;
26
	
27
	public int getFragmentsCounter() {
28
		return this.fragments.size();
29
	}
30
	
31
	public int[] getOperators() {
32
		if (operators.length != operatorCounter) {
33
			// resize
34
			System.arraycopy(this.operators, 0, (this.operators = new int[this.operatorCounter]), 0, this.operatorCounter);
35
		}
36
		return this.operators;
37
	}
38
	private boolean isSplittable(Expression expression) {
39
//		if (expression instanceof InfixExpression) {
40
//			InfixExpression infixExpression = (InfixExpression) expression;
41
//			return infixExpression.getLeftOperand() instanceof InfixExpression
42
//					||  infixExpression.getRightOperand() instanceof InfixExpression;
43
//		}
44
//		return false;
45
		return true;
46
	}
47
	public boolean visit(InfixExpression node) {
48
		final Expression leftOperand = node.getLeftOperand();
49
		final Expression rightOperand = node.getRightOperand();
50
		if (leftOperand.getNodeType() == ASTNode.INFIX_EXPRESSION && isSplittable(leftOperand)) {
51
			leftOperand.accept(this);
52
		} else {
53
			this.fragments.add(leftOperand);
54
		}
55
		if (operatorCounter == this.operators.length) {
56
			// need to resize
57
			System.arraycopy(this.operators, 0, (this.operators = new int[this.operatorCounter * 2]), 0, this.operatorCounter);
58
		}
59
		final int extractInfixExpressionOperator = CodeFormatterVisitor2.extractInfixExpressionOperator(node);
60
		this.operators[this.operatorCounter++] = extractInfixExpressionOperator;
61
		if (rightOperand.getNodeType() == ASTNode.INFIX_EXPRESSION && isSplittable(leftOperand)) {
62
			rightOperand.accept(this);
63
		} else {
64
			this.fragments.add(rightOperand);
65
		}
66
		final List extendedOperands = node.extendedOperands();
67
		final int extendedOperandsLength = extendedOperands.size();
68
		if (extendedOperandsLength != 0) {
69
			for (int i = 0; i < extendedOperandsLength; i++) {
70
				if (operatorCounter == this.operators.length) {
71
					// need to resize
72
					System.arraycopy(this.operators, 0, (this.operators = new int[this.operatorCounter * 2]), 0, this.operatorCounter);
73
				}
74
				this.operators[this.operatorCounter++] = extractInfixExpressionOperator;
75
				final Expression extendedOperand = ((Expression) extendedOperands.get(i));
76
				if (extendedOperand instanceof InfixExpression) {
77
					extendedOperand.accept(this);
78
				} else {
79
					this.fragments.add(extendedOperand);
80
				}
81
			}
82
		}
83
		return false;
84
	}
85
86
}
(-)formatter/org/eclipse/jdt/internal/formatter/Location2.java (-53 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.formatter;
12
13
/**
14
 * A location maintains positional information both in original source and in the output source.
15
 * It remembers source offsets, line/column and indentation level.
16
 * @since 2.1
17
 */
18
public class Location2 {
19
20
	public int inputOffset;
21
	public int outputLine;
22
	public int outputColumn;
23
	public int outputIndentationLevel;
24
	public boolean needSpace;
25
	public boolean pendingSpace;
26
	public int nlsTagCounter;
27
	public int numberOfIndentations;
28
29
	// chunk management
30
	public int lastNumberOfNewLines;
31
	
32
	// edits management
33
	int editsIndex;
34
	OptimizedReplaceEdit textEdit;
35
	
36
	public Location2(Scribe2 scribe, int sourceRestart){
37
		update(scribe, sourceRestart);
38
	}
39
	
40
	public void update(Scribe2 scribe, int sourceRestart){
41
		this.outputColumn = scribe.column;
42
		this.outputLine = scribe.line;
43
		this.inputOffset = sourceRestart;
44
		this.outputIndentationLevel = scribe.indentationLevel;
45
		this.lastNumberOfNewLines = scribe.lastNumberOfNewLines;
46
		this.needSpace = scribe.needSpace;
47
		this.pendingSpace = scribe.pendingSpace;
48
		this.editsIndex = scribe.editsIndex;
49
		this.nlsTagCounter = scribe.nlsTagCounter;
50
		this.numberOfIndentations = scribe.numberOfIndentations;
51
		textEdit = scribe.getLastEdit();
52
	}
53
}
(-)formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java (-161 / +12 lines)
Lines 16-26 Link Here
16
import org.eclipse.jdt.core.JavaCore;
16
import org.eclipse.jdt.core.JavaCore;
17
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
17
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
18
import org.eclipse.jdt.core.compiler.InvalidInputException;
18
import org.eclipse.jdt.core.compiler.InvalidInputException;
19
import org.eclipse.jdt.core.dom.AST;
20
import org.eclipse.jdt.core.dom.ASTParser;
21
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
22
import org.eclipse.jdt.core.dom.Block;
23
import org.eclipse.jdt.core.dom.CompilationUnit;
24
import org.eclipse.jdt.core.formatter.CodeFormatter;
19
import org.eclipse.jdt.core.formatter.CodeFormatter;
25
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
20
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
26
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
21
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
Lines 45-51 Link Here
45
40
46
	public static final boolean DEBUG = false;
41
	public static final boolean DEBUG = false;
47
	private static Scanner ProbingScanner;
42
	private static Scanner ProbingScanner;
48
	public static boolean USE_NEW_FORMATTER = false;
49
43
50
	/**
44
	/**
51
	 * Creates a comment region for a specific document partition type.
45
	 * Creates a comment region for a specific document partition type.
Lines 68-78 Link Here
68
		}
62
		}
69
		return null;
63
		return null;
70
	}
64
	}
65
71
	private CodeSnippetParsingUtil codeSnippetParsingUtil;
66
	private CodeSnippetParsingUtil codeSnippetParsingUtil;
72
	private Map defaultCompilerOptions;
67
	private Map defaultCompilerOptions;
73
	
68
	
74
	private CodeFormatterVisitor newCodeFormatter;
69
	private CodeFormatterVisitor newCodeFormatter;
75
	private CodeFormatterVisitor2 newCodeFormatter2;
76
	private Map options;
70
	private Map options;
77
	
71
	
78
	private DefaultCodeFormatterOptions preferences;
72
	private DefaultCodeFormatterOptions preferences;
Lines 174-197 Link Here
174
	}
168
	}
175
169
176
	private TextEdit formatClassBodyDeclarations(String source, int indentationLevel, String lineSeparator, int offset, int length) {
170
	private TextEdit formatClassBodyDeclarations(String source, int indentationLevel, String lineSeparator, int offset, int length) {
177
		if (USE_NEW_FORMATTER) {
178
			ASTParser parser = ASTParser.newParser(AST.JLS3);
179
			parser.setSource(source.toCharArray());
180
			parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
181
			parser.setCompilerOptions(getDefaultCompilerOptions());
182
			parser.setResolveBindings(false);
183
			parser.setUnitName(""); //$NON-NLS-1$
184
			org.eclipse.jdt.core.dom.ASTNode node = parser.createAST(null);
185
			if (lineSeparator != null) {
186
				this.preferences.line_separator = lineSeparator;
187
			} else {
188
				this.preferences.line_separator = Util.LINE_SEPARATOR;
189
			}
190
			this.preferences.initial_indentation_level = indentationLevel;
191
192
			this.newCodeFormatter2 = new CodeFormatterVisitor2(this.preferences, this.options, offset, length, (CompilationUnit) node.getRoot());
193
			return this.newCodeFormatter2.format(source, (AbstractTypeDeclaration) node);
194
		}
195
		ASTNode[] bodyDeclarations = this.codeSnippetParsingUtil.parseClassBodyDeclarations(source.toCharArray(), getDefaultCompilerOptions(), true);
171
		ASTNode[] bodyDeclarations = this.codeSnippetParsingUtil.parseClassBodyDeclarations(source.toCharArray(), getDefaultCompilerOptions(), true);
196
		
172
		
197
		if (bodyDeclarations == null) {
173
		if (bodyDeclarations == null) {
Lines 202-208 Link Here
202
	}
178
	}
203
179
204
	private TextEdit formatComment(int kind, String source, int indentationLevel, String lineSeparator, int offset, int length) {
180
	private TextEdit formatComment(int kind, String source, int indentationLevel, String lineSeparator, int offset, int length) {
205
		final boolean isFormattingComments = DefaultCodeFormatterConstants.TRUE.equals(this.options.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT));
181
		boolean isFormattingComments = false;
182
		switch (kind) {
183
			case CodeFormatter.K_SINGLE_LINE_COMMENT:
184
				isFormattingComments = DefaultCodeFormatterConstants.TRUE.equals(this.options.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_LINE_COMMENT));
185
				break;
186
			case CodeFormatter.K_MULTI_LINE_COMMENT:
187
				isFormattingComments = DefaultCodeFormatterConstants.TRUE.equals(this.options.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT));
188
				break;
189
			case CodeFormatter.K_JAVA_DOC:
190
				isFormattingComments = DefaultCodeFormatterConstants.TRUE.equals(this.options.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT));
191
		}
206
		if (isFormattingComments) {
192
		if (isFormattingComments) {
207
			if (lineSeparator != null) {
193
			if (lineSeparator != null) {
208
				this.preferences.line_separator = lineSeparator;
194
				this.preferences.line_separator = lineSeparator;
Lines 220-243 Link Here
220
	}
206
	}
221
207
222
	private TextEdit formatCompilationUnit(String source, int indentationLevel, String lineSeparator, int offset, int length) {
208
	private TextEdit formatCompilationUnit(String source, int indentationLevel, String lineSeparator, int offset, int length) {
223
		if (USE_NEW_FORMATTER) {
224
			ASTParser parser = ASTParser.newParser(AST.JLS3);
225
			parser.setSource(source.toCharArray());
226
			parser.setKind(ASTParser.K_COMPILATION_UNIT);
227
			parser.setCompilerOptions(getDefaultCompilerOptions());
228
			parser.setResolveBindings(false);
229
			parser.setUnitName(""); //$NON-NLS-1$
230
			org.eclipse.jdt.core.dom.ASTNode node = parser.createAST(null);
231
			if (lineSeparator != null) {
232
				this.preferences.line_separator = lineSeparator;
233
			} else {
234
				this.preferences.line_separator = Util.LINE_SEPARATOR;
235
			}
236
			this.preferences.initial_indentation_level = indentationLevel;
237
238
			this.newCodeFormatter2 = new CodeFormatterVisitor2(this.preferences, this.options, offset, length, (CompilationUnit) node.getRoot());
239
			return this.newCodeFormatter2.format(source, (CompilationUnit) node);
240
		}
241
		CompilationUnitDeclaration compilationUnitDeclaration = this.codeSnippetParsingUtil.parseCompilationUnit(source.toCharArray(), getDefaultCompilerOptions(), true);
209
		CompilationUnitDeclaration compilationUnitDeclaration = this.codeSnippetParsingUtil.parseCompilationUnit(source.toCharArray(), getDefaultCompilerOptions(), true);
242
		
210
		
243
		if (lineSeparator != null) {
211
		if (lineSeparator != null) {
Lines 253-279 Link Here
253
	}
221
	}
254
222
255
	private TextEdit formatExpression(String source, int indentationLevel, String lineSeparator, int offset, int length) {
223
	private TextEdit formatExpression(String source, int indentationLevel, String lineSeparator, int offset, int length) {
256
		if (USE_NEW_FORMATTER) {
257
			ASTParser parser = ASTParser.newParser(AST.JLS3);
258
			parser.setSource(source.toCharArray());
259
			parser.setKind(ASTParser.K_EXPRESSION);
260
			parser.setCompilerOptions(getDefaultCompilerOptions());
261
			parser.setResolveBindings(false);
262
			parser.setUnitName(""); //$NON-NLS-1$
263
			org.eclipse.jdt.core.dom.ASTNode node = parser.createAST(null);
264
			if (node.getNodeType() == org.eclipse.jdt.core.dom.ASTNode.COMPILATION_UNIT) return null;
265
			if (lineSeparator != null) {
266
				this.preferences.line_separator = lineSeparator;
267
			} else {
268
				this.preferences.line_separator = Util.LINE_SEPARATOR;
269
			}
270
			this.preferences.initial_indentation_level = indentationLevel;
271
272
			this.newCodeFormatter2 = new CodeFormatterVisitor2(this.preferences, this.options, offset, length, (CompilationUnit) node.getRoot());
273
			
274
			return this.newCodeFormatter2.format(source, (org.eclipse.jdt.core.dom.Expression) node);
275
		}
276
		
277
		Expression expression = this.codeSnippetParsingUtil.parseExpression(source.toCharArray(), getDefaultCompilerOptions(), true);
224
		Expression expression = this.codeSnippetParsingUtil.parseExpression(source.toCharArray(), getDefaultCompilerOptions(), true);
278
		
225
		
279
		if (expression == null) {
226
		if (expression == null) {
Lines 284-309 Link Here
284
	}
231
	}
285
232
286
	private TextEdit formatStatements(String source, int indentationLevel, String lineSeparator, int offset, int length) {
233
	private TextEdit formatStatements(String source, int indentationLevel, String lineSeparator, int offset, int length) {
287
		if (USE_NEW_FORMATTER) {
288
			ASTParser parser = ASTParser.newParser(AST.JLS3);
289
			parser.setSource(source.toCharArray());
290
			parser.setKind(ASTParser.K_STATEMENTS);
291
			parser.setCompilerOptions(getDefaultCompilerOptions());
292
			parser.setResolveBindings(false);
293
			parser.setUnitName(""); //$NON-NLS-1$
294
			org.eclipse.jdt.core.dom.ASTNode node = parser.createAST(null);
295
			if (lineSeparator != null) {
296
				this.preferences.line_separator = lineSeparator;
297
			} else {
298
				this.preferences.line_separator = Util.LINE_SEPARATOR;
299
			}
300
			this.preferences.initial_indentation_level = indentationLevel;
301
302
			this.newCodeFormatter2 = new CodeFormatterVisitor2(this.preferences, this.options, offset, length, (CompilationUnit) node.getRoot());
303
			
304
			return this.newCodeFormatter2.format(source, (Block) node);
305
		}
306
		
307
		ConstructorDeclaration constructorDeclaration = this.codeSnippetParsingUtil.parseStatements(source.toCharArray(), getDefaultCompilerOptions(), true, false);
234
		ConstructorDeclaration constructorDeclaration = this.codeSnippetParsingUtil.parseStatements(source.toCharArray(), getDefaultCompilerOptions(), true, false);
308
		
235
		
309
		if (constructorDeclaration.statements == null) {
236
		if (constructorDeclaration.statements == null) {
Lines 458-554 Link Here
458
		// probe for expression
385
		// probe for expression
459
		Expression expression = this.codeSnippetParsingUtil.parseExpression(source.toCharArray(), getDefaultCompilerOptions(), true);
386
		Expression expression = this.codeSnippetParsingUtil.parseExpression(source.toCharArray(), getDefaultCompilerOptions(), true);
460
		if (expression != null) {
387
		if (expression != null) {
461
			if (USE_NEW_FORMATTER) {
462
				ASTParser parser = ASTParser.newParser(AST.JLS3);
463
				parser.setSource(source.toCharArray());
464
				parser.setKind(ASTParser.K_EXPRESSION);
465
				parser.setCompilerOptions(getDefaultCompilerOptions());
466
				parser.setResolveBindings(false);
467
				parser.setUnitName(""); //$NON-NLS-1$
468
				org.eclipse.jdt.core.dom.ASTNode node = parser.createAST(null);
469
				if (node.getNodeType() == org.eclipse.jdt.core.dom.ASTNode.COMPILATION_UNIT) return null;
470
				if (lineSeparator != null) {
471
					this.preferences.line_separator = lineSeparator;
472
				} else {
473
					this.preferences.line_separator = Util.LINE_SEPARATOR;
474
				}
475
				this.preferences.initial_indentation_level = indentationLevel;
476
477
				this.newCodeFormatter2 = new CodeFormatterVisitor2(this.preferences, this.options, offset, length, (CompilationUnit) node.getRoot());
478
				
479
				TextEdit textEdit = this.newCodeFormatter2.format(source, (org.eclipse.jdt.core.dom.Expression) node);
480
				return textEdit;
481
			}			
482
			return internalFormatExpression(source, indentationLevel, lineSeparator, expression, offset, length);
388
			return internalFormatExpression(source, indentationLevel, lineSeparator, expression, offset, length);
483
		}
389
		}
484
390
485
		// probe for body declarations (fields, methods, constructors)
391
		// probe for body declarations (fields, methods, constructors)
486
		ASTNode[] bodyDeclarations = this.codeSnippetParsingUtil.parseClassBodyDeclarations(source.toCharArray(), getDefaultCompilerOptions(), true);
392
		ASTNode[] bodyDeclarations = this.codeSnippetParsingUtil.parseClassBodyDeclarations(source.toCharArray(), getDefaultCompilerOptions(), true);
487
		if (bodyDeclarations != null) {
393
		if (bodyDeclarations != null) {
488
			if (USE_NEW_FORMATTER) {
489
				ASTParser parser = ASTParser.newParser(AST.JLS3);
490
				parser.setSource(source.toCharArray());
491
				parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
492
				parser.setCompilerOptions(getDefaultCompilerOptions());
493
				parser.setResolveBindings(false);
494
				parser.setUnitName(""); //$NON-NLS-1$
495
				org.eclipse.jdt.core.dom.ASTNode node = parser.createAST(null);
496
				if (lineSeparator != null) {
497
					this.preferences.line_separator = lineSeparator;
498
				} else {
499
					this.preferences.line_separator = Util.LINE_SEPARATOR;
500
				}
501
				this.preferences.initial_indentation_level = indentationLevel;
502
503
				this.newCodeFormatter2 = new CodeFormatterVisitor2(this.preferences, this.options, offset, length, (CompilationUnit) node.getRoot());
504
				return this.newCodeFormatter2.format(source, (AbstractTypeDeclaration) node);
505
			}
506
			return internalFormatClassBodyDeclarations(source, indentationLevel, lineSeparator, bodyDeclarations, offset, length);
394
			return internalFormatClassBodyDeclarations(source, indentationLevel, lineSeparator, bodyDeclarations, offset, length);
507
		}
395
		}
508
396
509
		// probe for statements
397
		// probe for statements
510
		ConstructorDeclaration constructorDeclaration = this.codeSnippetParsingUtil.parseStatements(source.toCharArray(), getDefaultCompilerOptions(), true, false);
398
		ConstructorDeclaration constructorDeclaration = this.codeSnippetParsingUtil.parseStatements(source.toCharArray(), getDefaultCompilerOptions(), true, false);
511
		if (constructorDeclaration.statements != null) {
399
		if (constructorDeclaration.statements != null) {
512
			if (USE_NEW_FORMATTER) {
513
				ASTParser parser = ASTParser.newParser(AST.JLS3);
514
				parser.setSource(source.toCharArray());
515
				parser.setKind(ASTParser.K_STATEMENTS);
516
				parser.setCompilerOptions(getDefaultCompilerOptions());
517
				parser.setResolveBindings(false);
518
				parser.setUnitName(""); //$NON-NLS-1$
519
				org.eclipse.jdt.core.dom.ASTNode node = parser.createAST(null);
520
				if (lineSeparator != null) {
521
					this.preferences.line_separator = lineSeparator;
522
				} else {
523
					this.preferences.line_separator = Util.LINE_SEPARATOR;
524
				}
525
				this.preferences.initial_indentation_level = indentationLevel;
526
527
				this.newCodeFormatter2 = new CodeFormatterVisitor2(this.preferences, this.options, offset, length, (CompilationUnit) node.getRoot());
528
				
529
				return this.newCodeFormatter2.format(source, (Block) node);
530
			}
531
			return internalFormatStatements(source, indentationLevel, lineSeparator, constructorDeclaration, offset, length);
400
			return internalFormatStatements(source, indentationLevel, lineSeparator, constructorDeclaration, offset, length);
532
		}
401
		}
533
402
534
		if (USE_NEW_FORMATTER) {
535
			ASTParser parser = ASTParser.newParser(AST.JLS3);
536
			parser.setSource(source.toCharArray());
537
			parser.setKind(ASTParser.K_COMPILATION_UNIT);
538
			parser.setCompilerOptions(getDefaultCompilerOptions());
539
			parser.setResolveBindings(false);
540
			parser.setUnitName(""); //$NON-NLS-1$
541
			org.eclipse.jdt.core.dom.ASTNode node = parser.createAST(null);
542
			if (lineSeparator != null) {
543
				this.preferences.line_separator = lineSeparator;
544
			} else {
545
				this.preferences.line_separator = Util.LINE_SEPARATOR;
546
			}
547
			this.preferences.initial_indentation_level = indentationLevel;
548
549
			this.newCodeFormatter2 = new CodeFormatterVisitor2(this.preferences, this.options, offset, length, (CompilationUnit) node.getRoot());
550
			return this.newCodeFormatter2.format(source, (CompilationUnit) node);
551
		}
552
		// this has to be a compilation unit
403
		// this has to be a compilation unit
553
		return formatCompilationUnit(source, indentationLevel, lineSeparator, offset, length);
404
		return formatCompilationUnit(source, indentationLevel, lineSeparator, offset, length);
554
	}
405
	}
(-)formatter/org/eclipse/jdt/internal/formatter/Scribe2.java (-1506 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.formatter;
12
13
import java.util.Arrays;
14
import java.util.Collections;
15
import java.util.Comparator;
16
import java.util.List;
17
18
import org.eclipse.jdt.core.compiler.CharOperation;
19
import org.eclipse.jdt.core.compiler.InvalidInputException;
20
import org.eclipse.jdt.core.dom.ASTVisitor;
21
import org.eclipse.jdt.core.dom.Annotation;
22
import org.eclipse.jdt.core.dom.Comment;
23
import org.eclipse.jdt.core.dom.CompilationUnit;
24
import org.eclipse.jdt.internal.compiler.parser.Scanner;
25
import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
26
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
27
import org.eclipse.jdt.internal.compiler.util.Util;
28
import org.eclipse.jdt.internal.formatter.align.Alignment;
29
import org.eclipse.jdt.internal.formatter.align.Alignment2;
30
import org.eclipse.jdt.internal.formatter.align.AlignmentException;
31
import org.eclipse.text.edits.MultiTextEdit;
32
import org.eclipse.text.edits.ReplaceEdit;
33
import org.eclipse.text.edits.TextEdit;
34
35
/**
36
 * This class is responsible for dumping formatted source
37
 * @since 2.1
38
 */
39
public class Scribe2 {	private static final int INITIAL_SIZE = 100;
40
	
41
	private boolean checkLineWrapping;
42
	/** one-based column */
43
	public int column;
44
	private List comments;
45
		
46
	// Most specific alignment. 
47
	public Alignment2 currentAlignment;
48
	public int currentToken;
49
	
50
	// edits management
51
	private OptimizedReplaceEdit[] edits;
52
	public int editsIndex;
53
	
54
	public CodeFormatterVisitor2 formatter;
55
	public int indentationLevel;	
56
	public int lastNumberOfNewLines;
57
	public int line;
58
	
59
	private String lineSeparator;
60
	public Alignment2 memberAlignment;
61
	public boolean needSpace = false;
62
	
63
	public int nlsTagCounter;
64
	public int pageWidth;
65
	public boolean pendingSpace = false;
66
67
	public Scanner scanner;
68
	public int scannerEndPosition;
69
	public int tabLength;	
70
	public int indentationSize;	
71
	private int textRegionEnd;
72
	private int textRegionStart;
73
	public int tabChar;
74
	public int numberOfIndentations;
75
	private boolean useTabsOnlyForLeadingIndents;
76
	CompilationUnit unit;
77
78
    /** indent empty lines*/
79
    private final boolean indentEmptyLines;
80
81
	Scribe2(CodeFormatterVisitor2 formatter, long sourceLevel, int offset, int length, CompilationUnit unit) {
82
		this.scanner = new Scanner(true, true, false/*nls*/, sourceLevel/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
83
		this.formatter = formatter;
84
		this.pageWidth = formatter.preferences.page_width;
85
		this.tabLength = formatter.preferences.tab_size;
86
		this.indentationLevel= 0; // initialize properly
87
		this.numberOfIndentations = 0;
88
		this.useTabsOnlyForLeadingIndents = formatter.preferences.use_tabs_only_for_leading_indentations;
89
        this.indentEmptyLines = formatter.preferences.indent_empty_lines;
90
		this.tabChar = formatter.preferences.tab_char;
91
		if (this.tabChar == DefaultCodeFormatterOptions.MIXED) {
92
			this.indentationSize = formatter.preferences.indentation_size;
93
		} else {
94
			this.indentationSize = this.tabLength;
95
		}
96
		this.lineSeparator = formatter.preferences.line_separator;
97
		this.indentationLevel = formatter.preferences.initial_indentation_level * this.indentationSize;
98
		this.textRegionStart = offset;
99
		this.textRegionEnd = offset + length - 1;
100
		if (unit != null) {
101
			this.unit = unit;
102
			this.comments = unit.getCommentList();
103
		}
104
		reset();
105
	}
106
	
107
	private final void addDeleteEdit(int start, int end) {
108
		if (this.edits.length == this.editsIndex) {
109
			// resize
110
			resize();
111
		}
112
		addOptimizedReplaceEdit(start, end - start + 1, Util.EMPTY_STRING);
113
	}
114
115
	public final void addInsertEdit(int insertPosition, String insertedString) {
116
		if (this.edits.length == this.editsIndex) {
117
			// resize
118
			resize();
119
		}
120
		addOptimizedReplaceEdit(insertPosition, 0, insertedString);
121
	}
122
123
	private final void addOptimizedReplaceEdit(int offset, int length, String replacement) {
124
		if (this.editsIndex > 0) {
125
			// try to merge last two edits
126
			final OptimizedReplaceEdit previous = this.edits[this.editsIndex-1];
127
			final int previousOffset = previous.offset;
128
			final int previousLength = previous.length;
129
			final int endOffsetOfPreviousEdit = previousOffset + previousLength;
130
			final int replacementLength = replacement.length();
131
			final String previousReplacement = previous.replacement;
132
			final int previousReplacementLength = previousReplacement.length();
133
			if (previousOffset == offset && previousLength == length && (replacementLength == 0 || previousReplacementLength == 0)) {
134
				if (this.currentAlignment != null) {
135
					final Location2 location = this.currentAlignment.location;
136
					if (location.editsIndex == this.editsIndex) {
137
						location.editsIndex--;
138
						location.textEdit = previous;
139
					}
140
				}
141
				this.editsIndex--;
142
				return;
143
			}
144
			if (endOffsetOfPreviousEdit == offset) {
145
				if (length != 0) {
146
					if (replacementLength != 0) {
147
						this.edits[this.editsIndex - 1] = new OptimizedReplaceEdit(previousOffset, previousLength + length, previousReplacement + replacement);
148
					} else if (previousLength + length == previousReplacementLength) {
149
						// check the characters. If they are identical, we can get rid of the previous edit
150
						boolean canBeRemoved = true;
151
						loop: for (int i = previousOffset; i < previousOffset + previousReplacementLength; i++) {
152
							if (scanner.source[i] != previousReplacement.charAt(i - previousOffset)) {
153
								this.edits[this.editsIndex - 1] = new OptimizedReplaceEdit(previousOffset, previousReplacementLength, previousReplacement);
154
								canBeRemoved = false;
155
								break loop;
156
							}
157
						}
158
						if (canBeRemoved) {
159
							if (this.currentAlignment != null) {
160
								final Location2 location = this.currentAlignment.location;
161
								if (location.editsIndex == this.editsIndex) {
162
									location.editsIndex--;
163
									location.textEdit = previous;
164
								}
165
							}
166
							this.editsIndex--;
167
						}
168
					} else {
169
						this.edits[this.editsIndex - 1] = new OptimizedReplaceEdit(previousOffset, previousLength + length, previousReplacement);
170
					}
171
				} else {
172
					if (replacementLength != 0) {
173
						this.edits[this.editsIndex - 1] = new OptimizedReplaceEdit(previousOffset, previousLength, previousReplacement + replacement);
174
					}
175
				}
176
			} else {
177
				this.edits[this.editsIndex++] = new OptimizedReplaceEdit(offset, length, replacement);
178
			}
179
		} else {
180
			this.edits[this.editsIndex++] = new OptimizedReplaceEdit(offset, length, replacement);
181
		}
182
	}
183
	
184
	public final void addReplaceEdit(int start, int end, String replacement) {
185
		if (this.edits.length == this.editsIndex) {
186
			// resize
187
			resize();
188
		}
189
		addOptimizedReplaceEdit(start,  end - start + 1, replacement);
190
	}
191
192
	public void alignFragment(Alignment2 alignment, int fragmentIndex){
193
		alignment.fragmentIndex = fragmentIndex;
194
		alignment.checkColumn();
195
		alignment.performFragmentEffect();
196
	}
197
	
198
	public void checkNLSTag(int sourceStart) {
199
		if (hasNLSTag(sourceStart)) {
200
			this.nlsTagCounter++;
201
		}
202
	}
203
	public void consumeNextToken() {
204
		printComment();
205
		try {
206
			this.currentToken = this.scanner.getNextToken();
207
			addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
208
		} catch (InvalidInputException e) {
209
			throw new AbortFormatting(e);
210
		}
211
	}
212
	public Alignment2 createAlignment(String name, int mode, int count, int sourceRestart){
213
		return createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart);
214
	}
215
216
	public Alignment2 createAlignment(String name, int mode, int count, int sourceRestart, boolean adjust){
217
		return createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart, adjust);
218
	}
219
	
220
	public Alignment2 createAlignment(String name, int mode, int tieBreakRule, int count, int sourceRestart){
221
		return createAlignment(name, mode, tieBreakRule, count, sourceRestart, this.formatter.preferences.continuation_indentation, false);
222
	}
223
224
	public Alignment2 createAlignment(String name, int mode, int count, int sourceRestart, int continuationIndent, boolean adjust){
225
		return createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart, continuationIndent, adjust);
226
	}
227
228
	public Alignment2 createAlignment(String name, int mode, int tieBreakRule, int count, int sourceRestart, int continuationIndent, boolean adjust){
229
		Alignment2 alignment = new Alignment2(name, mode, tieBreakRule, this, count, sourceRestart, continuationIndent);
230
		// adjust break indentation
231
		if (adjust && this.memberAlignment != null) {
232
			Alignment2 current = this.memberAlignment;
233
			while (current.enclosing != null) {
234
				current = current.enclosing;
235
			}
236
			if ((current.mode & Alignment.M_MULTICOLUMN) != 0) {
237
				final int indentSize = this.indentationSize;
238
				switch(current.chunkKind) {
239
					case Alignment.CHUNK_METHOD :
240
					case Alignment.CHUNK_TYPE :
241
						if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
242
							alignment.breakIndentationLevel = this.indentationLevel + indentSize;
243
						} else {
244
							alignment.breakIndentationLevel = this.indentationLevel + continuationIndent * indentSize;
245
						}
246
						alignment.update();
247
						break;
248
					case Alignment.CHUNK_FIELD :
249
						if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
250
							alignment.breakIndentationLevel = current.originalIndentationLevel + indentSize;
251
						} else {
252
							alignment.breakIndentationLevel = current.originalIndentationLevel + continuationIndent * indentSize;
253
						}
254
						alignment.update();
255
						break;
256
				}
257
			} else {
258
				switch(current.mode & Alignment.SPLIT_MASK) {
259
					case Alignment.M_COMPACT_SPLIT :
260
					case Alignment.M_COMPACT_FIRST_BREAK_SPLIT :
261
					case Alignment.M_NEXT_PER_LINE_SPLIT :
262
					case Alignment.M_NEXT_SHIFTED_SPLIT :
263
					case Alignment.M_ONE_PER_LINE_SPLIT :
264
						final int indentSize = this.indentationSize;
265
						switch(current.chunkKind) {
266
							case Alignment.CHUNK_METHOD :
267
							case Alignment.CHUNK_TYPE :
268
								if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
269
									alignment.breakIndentationLevel = this.indentationLevel + indentSize;
270
								} else {
271
									alignment.breakIndentationLevel = this.indentationLevel + continuationIndent * indentSize;
272
								}
273
								alignment.update();
274
								break;
275
							case Alignment.CHUNK_FIELD :
276
								if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
277
									alignment.breakIndentationLevel = current.originalIndentationLevel + indentSize;
278
								} else {
279
									alignment.breakIndentationLevel = current.originalIndentationLevel + continuationIndent * indentSize;
280
								}
281
								alignment.update();
282
								break;
283
						}
284
						break;
285
				}
286
			}
287
		}
288
		return alignment; 
289
	}
290
291
	public Alignment2 createMemberAlignment(String name, int mode, int count, int sourceRestart) {
292
		Alignment2 mAlignment = createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart);
293
		mAlignment.breakIndentationLevel = this.indentationLevel;
294
		return mAlignment;
295
	}
296
	
297
	public void enterAlignment(Alignment2 alignment){
298
		alignment.enclosing = this.currentAlignment;
299
		this.currentAlignment = alignment;
300
	}
301
302
	public void enterMemberAlignment(Alignment2 alignment) {
303
		alignment.enclosing = this.memberAlignment;
304
		this.memberAlignment = alignment;
305
	}
306
307
	public void exitAlignment(Alignment2 alignment, boolean discardAlignment){
308
		Alignment2 current = this.currentAlignment;
309
		while (current != null){
310
			if (current == alignment) break;
311
			current = current.enclosing;
312
		}
313
		if (current == null) {
314
			throw new AbortFormatting("could not find matching alignment: "+alignment); //$NON-NLS-1$
315
		}
316
		this.indentationLevel = alignment.location.outputIndentationLevel;
317
		this.numberOfIndentations = alignment.location.numberOfIndentations;
318
		if (discardAlignment){ 
319
			this.currentAlignment = alignment.enclosing;
320
		}
321
	}
322
	
323
	public void exitMemberAlignment(Alignment2 alignment){
324
		Alignment2 current = this.memberAlignment;
325
		while (current != null){
326
			if (current == alignment) break;
327
			current = current.enclosing;
328
		}
329
		if (current == null) {
330
			throw new AbortFormatting("could not find matching alignment: "+alignment); //$NON-NLS-1$
331
		}
332
		this.indentationLevel = current.location.outputIndentationLevel;
333
		this.numberOfIndentations = current.location.numberOfIndentations;
334
		this.memberAlignment = current.enclosing;
335
	}
336
	
337
	public Alignment2 getAlignment(String name){
338
		if (this.currentAlignment != null) {
339
			return this.currentAlignment.getAlignment(name);
340
		}
341
		return null;
342
	}
343
	
344
	/** 
345
	 * Answer actual indentation level based on true column position
346
	 * @return int
347
	 */
348
	public int getColumnIndentationLevel() {
349
		return this.column - 1;
350
	}	
351
	
352
	public String getEmptyLines(int linesNumber) {
353
		if (this.nlsTagCounter > 0) {
354
			return Util.EMPTY_STRING;
355
		}
356
		StringBuffer buffer = new StringBuffer();
357
		if (lastNumberOfNewLines == 0) {
358
			linesNumber++; // add an extra line breaks
359
			for (int i = 0; i < linesNumber; i++) {
360
                if (indentEmptyLines) printIndentationIfNecessary(buffer);
361
				buffer.append(this.lineSeparator);
362
			}
363
			lastNumberOfNewLines += linesNumber;
364
			line += linesNumber;
365
			column = 1;
366
			needSpace = false;
367
			this.pendingSpace = false;
368
		} else if (lastNumberOfNewLines == 1) {
369
			for (int i = 0; i < linesNumber; i++) {
370
                if (indentEmptyLines) printIndentationIfNecessary(buffer);
371
				buffer.append(this.lineSeparator);
372
			}
373
			lastNumberOfNewLines += linesNumber;
374
			line += linesNumber;
375
			column = 1;
376
			needSpace = false;
377
			this.pendingSpace = false;
378
		} else {
379
			if ((lastNumberOfNewLines - 1) >= linesNumber) {
380
				// there is no need to add new lines
381
				return Util.EMPTY_STRING;
382
			}
383
			final int realNewLineNumber = linesNumber - lastNumberOfNewLines + 1;
384
			for (int i = 0; i < realNewLineNumber; i++) {
385
                if (indentEmptyLines) printIndentationIfNecessary(buffer);
386
				buffer.append(this.lineSeparator);
387
			}
388
			lastNumberOfNewLines += realNewLineNumber;
389
			line += realNewLineNumber;
390
			column = 1;
391
			needSpace = false;
392
			this.pendingSpace = false;
393
		}
394
		return String.valueOf(buffer);
395
	}
396
397
	public OptimizedReplaceEdit getLastEdit() {
398
		if (this.editsIndex > 0) {
399
			return this.edits[this.editsIndex - 1];
400
		}
401
		return null;
402
	}
403
	Alignment2 getMemberAlignment() {
404
		return this.memberAlignment;
405
	}
406
	
407
	public String getNewLine() {
408
		if (this.nlsTagCounter > 0) {
409
			return Util.EMPTY_STRING;
410
		}
411
		if (lastNumberOfNewLines >= 1) {
412
			column = 1; // ensure that the scribe is at the beginning of a new line
413
			return Util.EMPTY_STRING;
414
		}
415
		line++;
416
		lastNumberOfNewLines = 1;
417
		column = 1;
418
		needSpace = false;
419
		this.pendingSpace = false;
420
		return this.lineSeparator;
421
	}
422
423
	/** 
424
	 * Answer next indentation level based on column estimated position
425
	 * (if column is not indented, then use indentationLevel)
426
	 */
427
	public int getNextIndentationLevel(int someColumn) {
428
		int indent = someColumn - 1;
429
		if (indent == 0)
430
			return this.indentationLevel;
431
		if (this.tabChar == DefaultCodeFormatterOptions.TAB) {
432
			if (this.useTabsOnlyForLeadingIndents) {
433
				return indent;
434
			}
435
			int rem = indent % this.indentationSize;
436
			int addition = rem == 0 ? 0 : this.indentationSize - rem; // round to superior
437
			return indent + addition;
438
		} else {
439
			return indent;
440
		}
441
	}
442
443
	private String getPreserveEmptyLines(int count) {
444
		if (count > 0) {
445
			if (this.formatter.preferences.number_of_empty_lines_to_preserve != 0) {
446
				int linesToPreserve = Math.min(count, this.formatter.preferences.number_of_empty_lines_to_preserve);
447
				return this.getEmptyLines(linesToPreserve);
448
			} else {
449
				return getNewLine();
450
			}
451
		}
452
		return Util.EMPTY_STRING;
453
	}
454
	
455
	public TextEdit getRootEdit() {
456
		MultiTextEdit edit = null;
457
		int length = this.textRegionEnd - this.textRegionStart + 1;
458
		if (this.textRegionStart <= 0) {
459
			if (length <= 0) {
460
				edit = new MultiTextEdit(0, 0);
461
			} else {
462
				edit = new MultiTextEdit(0, this.textRegionEnd + 1);
463
			}
464
		} else {
465
			edit = new MultiTextEdit(this.textRegionStart, this.textRegionEnd - this.textRegionStart + 1);
466
		}
467
		for (int i= 0, max = this.editsIndex; i < max; i++) {
468
			OptimizedReplaceEdit currentEdit = edits[i];
469
			if (isValidEdit(currentEdit)) {
470
				edit.addChild(new ReplaceEdit(currentEdit.offset, currentEdit.length, currentEdit.replacement));
471
			}
472
		}
473
		this.edits = null;
474
		return edit;
475
	}
476
	
477
	public void handleLineTooLong() {
478
		// search for closest breakable alignment, using tiebreak rules
479
		// look for outermost breakable one
480
		int relativeDepth = 0, outerMostDepth = -1;
481
		Alignment2 targetAlignment = this.currentAlignment;
482
		while (targetAlignment != null){
483
			if (targetAlignment.tieBreakRule == Alignment.R_OUTERMOST && targetAlignment.couldBreak()){
484
				outerMostDepth = relativeDepth;
485
			}
486
			targetAlignment = targetAlignment.enclosing;
487
			relativeDepth++;
488
		}
489
		if (outerMostDepth >= 0) {
490
			throw new AlignmentException(AlignmentException.LINE_TOO_LONG, outerMostDepth);
491
		}
492
		// look for innermost breakable one
493
		relativeDepth = 0;
494
		targetAlignment = this.currentAlignment;
495
		while (targetAlignment != null){
496
			if (targetAlignment.couldBreak()){
497
				throw new AlignmentException(AlignmentException.LINE_TOO_LONG, relativeDepth);
498
			}
499
			targetAlignment = targetAlignment.enclosing;
500
			relativeDepth++;
501
		}
502
		// did not find any breakable location - proceed
503
	}
504
505
	/*
506
	 * Check if there is a NLS tag on this line. If yes, return true, returns false otherwise.
507
	 */
508
	private boolean hasNLSTag(int sourceStart) {
509
		final Comment comment = this.unit.getAST().newBlockComment();
510
		comment.setSourceRange(sourceStart, 1);
511
		int index = Collections.binarySearch(this.comments, comment, new Comparator() {
512
			public int compare(Object o1, Object o2) {
513
				Comment comment1 = (Comment) o1;
514
				Comment comment2 = (Comment) o2;
515
				return comment1.getStartPosition() - comment2.getStartPosition();
516
			}
517
		});
518
		final int lineNumber = this.unit.getLineNumber(sourceStart);
519
		if (index < 0) {
520
			index = -index - 1;
521
			final int commentLength = this.comments.size();
522
			for (int i = index; i < commentLength; i++) {
523
				Comment currentComment = (Comment) comments.get(i);
524
				final int start = currentComment.getStartPosition();
525
				if (this.unit.getLineNumber(start) == lineNumber) {
526
					if (currentComment.isLineComment()) {
527
						return CharOperation.indexOf(Scanner.TAG_PREFIX, this.scanner.source, true, start) != -1;
528
					}
529
				} else {
530
					return false;
531
				}
532
			}
533
		}
534
		return false;
535
	}
536
	
537
	public void indent() {
538
		this.indentationLevel += this.indentationSize;
539
		this.numberOfIndentations++;
540
	}	
541
542
	/**
543
	 * @param compilationUnitSource
544
	 */
545
	public void initializeScanner(char[] compilationUnitSource) {
546
		this.scanner.setSource(compilationUnitSource);
547
		this.scannerEndPosition = compilationUnitSource.length;
548
		this.scanner.resetTo(0, this.scannerEndPosition);
549
		this.edits = new OptimizedReplaceEdit[INITIAL_SIZE];
550
	}	
551
	
552
	private boolean isValidEdit(OptimizedReplaceEdit edit) {
553
		final int editLength= edit.length;
554
		final int editReplacementLength= edit.replacement.length();
555
		final int editOffset= edit.offset;
556
		if (editLength != 0) {
557
			if (this.textRegionStart <= editOffset && (editOffset + editLength - 1) <= this.textRegionEnd) {
558
				if (editReplacementLength != 0 && editLength == editReplacementLength) {
559
					for (int i = editOffset, max = editOffset + editLength; i < max; i++) {
560
						if (scanner.source[i] != edit.replacement.charAt(i - editOffset)) {
561
							return true;
562
						}
563
					}
564
					return false;
565
				} else {
566
					return true;
567
				}
568
			} else if (editOffset + editLength == this.textRegionStart) {
569
				int i = editOffset;
570
				for (int max = editOffset + editLength; i < max; i++) {
571
					int replacementStringIndex = i - editOffset;
572
					if (replacementStringIndex >= editReplacementLength || scanner.source[i] != edit.replacement.charAt(replacementStringIndex)) {
573
						break;
574
					}
575
				}
576
				if (i - editOffset != editReplacementLength && i != editOffset + editLength - 1) {
577
					edit.offset = textRegionStart;
578
					edit.length = 0;
579
					edit.replacement = edit.replacement.substring(i - editOffset);
580
					return true;
581
				}
582
			}
583
		} else if (this.textRegionStart <= editOffset && editOffset <= this.textRegionEnd) {
584
			return true;
585
		} else if (editOffset == this.scannerEndPosition && editOffset == this.textRegionEnd + 1) {
586
			return true;
587
		}
588
		return false;
589
	}
590
591
	private void preserveEmptyLines(int count, int insertPosition) {
592
		if (count > 0) {
593
			if (this.formatter.preferences.number_of_empty_lines_to_preserve != 0) {
594
				int linesToPreserve = Math.min(count, this.formatter.preferences.number_of_empty_lines_to_preserve);
595
				this.printEmptyLines(linesToPreserve, insertPosition);
596
			} else {
597
				printNewLine(insertPosition);
598
			}
599
		}
600
	}
601
602
	private void print(char[] s, boolean considerSpaceIfAny) {
603
		if (checkLineWrapping && s.length + column > this.pageWidth) {
604
			handleLineTooLong();
605
		}
606
		this.lastNumberOfNewLines = 0;
607
		printIndentationIfNecessary();
608
		if (considerSpaceIfAny) {
609
			this.space();
610
		}
611
		if (this.pendingSpace) {
612
			this.addInsertEdit(this.scanner.getCurrentTokenStartPosition(), " "); //$NON-NLS-1$
613
		}
614
		this.pendingSpace = false;	
615
		this.needSpace = false;		
616
		column += s.length;
617
		needSpace = true;
618
	}
619
620
	private void printBlockComment(char[] s, boolean isJavadoc) {
621
		int currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition();
622
		int currentTokenEndPosition = this.scanner.getCurrentTokenEndPosition() + 1;
623
		
624
		this.scanner.resetTo(currentTokenStartPosition, currentTokenEndPosition - 1);
625
		int currentCharacter;
626
		boolean isNewLine = false;
627
		int start = currentTokenStartPosition;
628
		int nextCharacterStart = currentTokenStartPosition;
629
		printIndentationIfNecessary();
630
		if (this.pendingSpace) {
631
			this.addInsertEdit(currentTokenStartPosition, " "); //$NON-NLS-1$
632
		}
633
		this.needSpace = false;		
634
		this.pendingSpace = false;		
635
		int previousStart = currentTokenStartPosition;
636
637
		while (nextCharacterStart <= currentTokenEndPosition && (currentCharacter = this.scanner.getNextChar()) != -1) {
638
			nextCharacterStart = this.scanner.currentPosition;
639
640
			switch(currentCharacter) {
641
				case '\r' :
642
					start = previousStart;
643
					isNewLine = true;
644
					if (this.scanner.getNextChar('\n')) {
645
						currentCharacter = '\n';
646
						nextCharacterStart = this.scanner.currentPosition;
647
					}
648
					break;
649
				case '\n' :
650
					start = previousStart;
651
					isNewLine = true;
652
					break;
653
				default:
654
					if (isNewLine) {
655
						if (ScannerHelper.isWhitespace((char) currentCharacter)) {
656
							int previousStartPosition = this.scanner.currentPosition;
657
							while(currentCharacter != -1 && currentCharacter != '\r' && currentCharacter != '\n' && ScannerHelper.isWhitespace((char) currentCharacter)) {
658
								previousStart = nextCharacterStart;
659
								previousStartPosition = this.scanner.currentPosition;
660
								currentCharacter = this.scanner.getNextChar();
661
								nextCharacterStart = this.scanner.currentPosition;
662
							}
663
							if (currentCharacter == '\r' || currentCharacter == '\n') {
664
								nextCharacterStart = previousStartPosition;
665
							}
666
						}
667
						this.column = 1;
668
						this.line++;
669
670
						StringBuffer buffer = new StringBuffer();
671
						buffer.append(this.lineSeparator);
672
						printIndentationIfNecessary(buffer);
673
						buffer.append(' ');
674
				
675
						addReplaceEdit(start, previousStart - 1, String.valueOf(buffer));
676
					} else {
677
						this.column += (nextCharacterStart - previousStart);
678
					}
679
					isNewLine = false;
680
			}
681
			previousStart = nextCharacterStart;
682
			this.scanner.currentPosition = nextCharacterStart;
683
		}
684
		this.lastNumberOfNewLines = 0;
685
		needSpace = false;
686
		this.scanner.resetTo(currentTokenEndPosition, this.scannerEndPosition - 1);
687
		if (isJavadoc) {
688
			printNewLine();
689
		}
690
	}
691
	
692
	public void printEndOfCompilationUnit() {
693
		try {
694
			// if we have a space between two tokens we ensure it will be dumped in the formatted string
695
			int currentTokenStartPosition = this.scanner.currentPosition;
696
			boolean hasComment = false;
697
			boolean hasLineComment = false;
698
			boolean hasWhitespace = false;
699
			int count = 0;
700
			while (true) {
701
				this.currentToken = this.scanner.getNextToken();
702
				switch(this.currentToken) {
703
					case TerminalTokens.TokenNameWHITESPACE :
704
						char[] whiteSpaces = this.scanner.getCurrentTokenSource();
705
						count = 0;
706
						for (int i = 0, max = whiteSpaces.length; i < max; i++) {
707
							switch(whiteSpaces[i]) {
708
								case '\r' :
709
									if ((i + 1) < max) {
710
										if (whiteSpaces[i + 1] == '\n') {
711
											i++;
712
										}
713
									}
714
									count++;
715
									break;
716
								case '\n' :
717
									count++;
718
							}
719
						}
720
						if (count == 0) {
721
							hasWhitespace = true;
722
							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
723
						} else if (hasComment) {
724
							if (count == 1) {
725
								this.printNewLine(this.scanner.getCurrentTokenStartPosition());
726
							} else {
727
								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
728
							}
729
							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
730
						} else if (hasLineComment) {
731
							this.preserveEmptyLines(count, this.scanner.getCurrentTokenStartPosition());
732
							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
733
						} else {
734
							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
735
						}
736
						currentTokenStartPosition = this.scanner.currentPosition;						
737
						break;
738
					case TerminalTokens.TokenNameCOMMENT_LINE :
739
						if (count >= 1) {
740
							if (count > 1) {
741
								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
742
							} else if (count == 1) {
743
								printNewLine(this.scanner.getCurrentTokenStartPosition());
744
							}
745
						} else if (hasWhitespace) {
746
							space();
747
						} 
748
						hasWhitespace = false;
749
						this.printCommentLine(this.scanner.getRawTokenSource());
750
						currentTokenStartPosition = this.scanner.currentPosition;
751
						hasLineComment = true;		
752
						count = 0;
753
						break;
754
					case TerminalTokens.TokenNameCOMMENT_BLOCK :
755
						if (count >= 1) {
756
							if (count > 1) {
757
								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
758
							} else if (count == 1) {
759
								printNewLine(this.scanner.getCurrentTokenStartPosition());
760
							}
761
						} else if (hasWhitespace) {
762
							space();
763
						} 
764
						hasWhitespace = false;
765
						this.printBlockComment(this.scanner.getRawTokenSource(), false);
766
						currentTokenStartPosition = this.scanner.currentPosition;
767
						hasLineComment = false;
768
						hasComment = true;
769
						count = 0;
770
						break;
771
					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
772
						if (count >= 1) {
773
							if (count > 1) {
774
								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
775
							} else if (count == 1) {
776
								printNewLine(this.scanner.getCurrentTokenStartPosition());
777
							}
778
						} else if (hasWhitespace) {
779
							space();
780
						} 
781
						hasWhitespace = false;
782
						this.printBlockComment(this.scanner.getRawTokenSource(), true);
783
						currentTokenStartPosition = this.scanner.currentPosition;
784
						hasLineComment = false;
785
						hasComment = true;
786
						count = 0;
787
						break;
788
					case TerminalTokens.TokenNameSEMICOLON :
789
						char[] currentTokenSource = this.scanner.getRawTokenSource();
790
						this.print(currentTokenSource, this.formatter.preferences.insert_space_before_semicolon);
791
						break;
792
					case TerminalTokens.TokenNameEOF :
793
						if (count >= 1 || this.formatter.preferences.insert_new_line_at_end_of_file_if_missing) {
794
							this.printNewLine(this.scannerEndPosition);
795
						}
796
						return;
797
					default :
798
						// step back one token
799
						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
800
						return;
801
				}
802
			}
803
		} catch (InvalidInputException e) {
804
			throw new AbortFormatting(e);
805
		}
806
	}
807
808
	public void printComment() {
809
		try {
810
			// if we have a space between two tokens we ensure it will be dumped in the formatted string
811
			int currentTokenStartPosition = this.scanner.currentPosition;
812
			boolean hasComment = false;
813
			boolean hasLineComment = false;
814
			boolean hasWhitespace = false;
815
			int count = 0;
816
			while ((this.currentToken = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
817
				switch(this.currentToken) {
818
					case TerminalTokens.TokenNameWHITESPACE :
819
						char[] whiteSpaces = this.scanner.getCurrentTokenSource();
820
						count = 0;
821
						for (int i = 0, max = whiteSpaces.length; i < max; i++) {
822
							switch(whiteSpaces[i]) {
823
								case '\r' :
824
									if ((i + 1) < max) {
825
										if (whiteSpaces[i + 1] == '\n') {
826
											i++;
827
										}
828
									}
829
									count++;
830
									break;
831
								case '\n' :
832
									count++;
833
							}
834
						}
835
						if (count == 0) {
836
							hasWhitespace = true;
837
							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
838
						} else if (hasComment) {
839
							if (count == 1) {
840
								this.printNewLine(this.scanner.getCurrentTokenStartPosition());
841
							} else {
842
								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
843
							}
844
							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
845
						} else if (hasLineComment) {
846
							this.preserveEmptyLines(count, this.scanner.getCurrentTokenStartPosition());
847
							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
848
						} else if (count != 0 && this.formatter.preferences.number_of_empty_lines_to_preserve != 0) {
849
							addReplaceEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition(), this.getPreserveEmptyLines(count - 1));
850
						} else {
851
							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
852
						}
853
						currentTokenStartPosition = this.scanner.currentPosition;						
854
						break;
855
					case TerminalTokens.TokenNameCOMMENT_LINE :
856
						if (count >= 1) {
857
							if (count > 1) {
858
								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
859
							} else if (count == 1) {
860
								printNewLine(this.scanner.getCurrentTokenStartPosition());
861
							}
862
						} else if (hasWhitespace) {
863
							space();
864
						} 
865
						hasWhitespace = false;
866
						this.printCommentLine(this.scanner.getRawTokenSource());
867
						currentTokenStartPosition = this.scanner.currentPosition;
868
						hasLineComment = true;		
869
						count = 0;
870
						break;
871
					case TerminalTokens.TokenNameCOMMENT_BLOCK :
872
						if (count >= 1) {
873
							if (count > 1) {
874
								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
875
							} else if (count == 1) {
876
								printNewLine(this.scanner.getCurrentTokenStartPosition());
877
							}
878
						} else if (hasWhitespace) {
879
							space();
880
						} 
881
						hasWhitespace = false;
882
						this.printBlockComment(this.scanner.getRawTokenSource(), false);
883
						currentTokenStartPosition = this.scanner.currentPosition;
884
						hasLineComment = false;
885
						hasComment = true;
886
						count = 0;
887
						break;
888
					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
889
						if (count >= 1) {
890
							if (count > 1) {
891
								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
892
							} else if (count == 1) {
893
								printNewLine(this.scanner.getCurrentTokenStartPosition());
894
							}
895
						} else if (hasWhitespace) {
896
							space();
897
						} 
898
						hasWhitespace = false;
899
						this.printBlockComment(this.scanner.getRawTokenSource(), true);
900
						currentTokenStartPosition = this.scanner.currentPosition;
901
						hasLineComment = false;
902
						hasComment = true;
903
						count = 0;
904
						break;
905
					default :
906
						// step back one token
907
						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
908
						return;
909
				}
910
			}
911
		} catch (InvalidInputException e) {
912
			throw new AbortFormatting(e);
913
		}
914
	}
915
	
916
	private void printCommentLine(char[] s) {
917
		int currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition();
918
		int currentTokenEndPosition = this.scanner.getCurrentTokenEndPosition() + 1;
919
		if (CharOperation.indexOf(Scanner.TAG_PREFIX, this.scanner.source, true, currentTokenStartPosition) != -1) {
920
			this.nlsTagCounter = 0;
921
		}
922
		this.scanner.resetTo(currentTokenStartPosition, currentTokenEndPosition - 1);
923
		int currentCharacter;
924
		int start = currentTokenStartPosition;
925
		int nextCharacterStart = currentTokenStartPosition;
926
		printIndentationIfNecessary();
927
		if (this.pendingSpace) {
928
			this.addInsertEdit(currentTokenStartPosition, " "); //$NON-NLS-1$
929
		}
930
		this.needSpace = false;		
931
		this.pendingSpace = false;		
932
		int previousStart = currentTokenStartPosition;
933
934
		loop: while (nextCharacterStart <= currentTokenEndPosition && (currentCharacter = this.scanner.getNextChar()) != -1) {
935
			nextCharacterStart = this.scanner.currentPosition;
936
937
			switch(currentCharacter) {
938
				case '\r' :
939
					start = previousStart;
940
					break loop;
941
				case '\n' :
942
					start = previousStart;
943
					break loop;
944
			}
945
			previousStart = nextCharacterStart;
946
		}
947
		if (start != currentTokenStartPosition) {
948
			addReplaceEdit(start, currentTokenEndPosition - 1, lineSeparator);
949
		}
950
		line++; 
951
		column = 1;
952
		needSpace = false;
953
		this.pendingSpace = false;
954
		lastNumberOfNewLines = 1;
955
		// realign to the proper value
956
		if (this.currentAlignment != null) {
957
			if (this.memberAlignment != null) {
958
				// select the last alignment
959
				if (this.currentAlignment.location.inputOffset > this.memberAlignment.location.inputOffset) {
960
					if (this.currentAlignment.couldBreak() && this.currentAlignment.wasSplit) {
961
						this.currentAlignment.performFragmentEffect();
962
					}
963
				} else {
964
					this.indentationLevel = Math.max(this.indentationLevel, this.memberAlignment.breakIndentationLevel);
965
				}
966
			} else if (this.currentAlignment.couldBreak() && this.currentAlignment.wasSplit) {
967
				this.currentAlignment.performFragmentEffect();
968
			}
969
		}
970
		this.scanner.resetTo(currentTokenEndPosition, this.scannerEndPosition - 1);
971
	}
972
	public void printEmptyLines(int linesNumber) {
973
		this.printEmptyLines(linesNumber, this.scanner.getCurrentTokenEndPosition() + 1);
974
	}
975
976
	private void printEmptyLines(int linesNumber, int insertPosition) {
977
        final String buffer = getEmptyLines(linesNumber);
978
        if (Util.EMPTY_STRING == buffer) return;
979
        
980
		addInsertEdit(insertPosition, buffer);
981
	}
982
983
	void printIndentationIfNecessary() {
984
		StringBuffer buffer = new StringBuffer();
985
		printIndentationIfNecessary(buffer);
986
		if (buffer.length() > 0) {
987
			addInsertEdit(this.scanner.getCurrentTokenStartPosition(), buffer.toString());
988
			this.pendingSpace = false;
989
		}
990
	}
991
992
	private void printIndentationIfNecessary(StringBuffer buffer) {
993
		switch(this.tabChar) {
994
			case DefaultCodeFormatterOptions.TAB :
995
				boolean useTabsForLeadingIndents = this.useTabsOnlyForLeadingIndents;
996
				int numberOfLeadingIndents = this.numberOfIndentations;
997
				int indentationsAsTab = 0;
998
				if (useTabsForLeadingIndents) {
999
					while (this.column <= this.indentationLevel) {
1000
						if (indentationsAsTab < numberOfLeadingIndents) {
1001
							buffer.append('\t');
1002
							indentationsAsTab++;
1003
							this.lastNumberOfNewLines = 0;
1004
							int complement = this.tabLength - ((this.column - 1) % this.tabLength); // amount of space
1005
							this.column += complement;
1006
							this.needSpace = false;
1007
						} else {
1008
							buffer.append(' ');
1009
							this.column++;
1010
							this.needSpace = false;
1011
						}
1012
					}
1013
				} else {
1014
					while (this.column <= this.indentationLevel) {
1015
						buffer.append('\t');
1016
						this.lastNumberOfNewLines = 0;
1017
						int complement = this.tabLength - ((this.column - 1) % this.tabLength); // amount of space
1018
						this.column += complement;
1019
						this.needSpace = false;
1020
					}
1021
				}
1022
				break;
1023
			case DefaultCodeFormatterOptions.SPACE :
1024
				while (this.column <= this.indentationLevel) {
1025
					buffer.append(' ');
1026
					this.column++;
1027
					this.needSpace = false;
1028
				}
1029
				break;
1030
			case DefaultCodeFormatterOptions.MIXED :
1031
				useTabsForLeadingIndents = this.useTabsOnlyForLeadingIndents;
1032
				numberOfLeadingIndents = this.numberOfIndentations;
1033
				indentationsAsTab = 0;
1034
				if (useTabsForLeadingIndents) {
1035
					final int columnForLeadingIndents = numberOfLeadingIndents * this.indentationSize;
1036
					while (this.column <= this.indentationLevel) {
1037
						if (this.column <= columnForLeadingIndents) {
1038
							if ((this.column - 1 + this.tabLength) <= this.indentationLevel) {
1039
								buffer.append('\t');
1040
								this.column += this.tabLength;
1041
							} else if ((this.column - 1 + this.indentationSize) <= this.indentationLevel) {
1042
								// print one indentation
1043
								for (int i = 0, max = this.indentationSize; i < max; i++) {
1044
									buffer.append(' ');
1045
									this.column++;
1046
								}
1047
							} else {
1048
								buffer.append(' ');
1049
								this.column++;
1050
							}
1051
						} else {
1052
							for (int i = this.column, max = this.indentationLevel; i <= max; i++) {
1053
								buffer.append(' ');
1054
								this.column++;
1055
							}
1056
						}
1057
						this.needSpace = false;
1058
					}
1059
				} else {
1060
					while (this.column <= this.indentationLevel) {
1061
						if ((this.column - 1 + this.tabLength) <= this.indentationLevel) {
1062
							buffer.append('\t');
1063
							this.column += this.tabLength;
1064
						} else if ((this.column - 1 + this.indentationSize) <= this.indentationLevel) {
1065
							// print one indentation
1066
							for (int i = 0, max = this.indentationSize; i < max; i++) {
1067
								buffer.append(' ');
1068
								this.column++;
1069
							}
1070
						} else {
1071
							buffer.append(' ');
1072
							this.column++;
1073
						}
1074
						this.needSpace = false;
1075
					}
1076
				}
1077
				break;
1078
		}
1079
	}
1080
1081
	/**
1082
	 * @param modifiers list of IExtendedModifiers
1083
	 * @param visitor
1084
	 */
1085
	public void printModifiers(List modifiers, ASTVisitor visitor) {
1086
		try {
1087
			int modifiersIndex = 0;
1088
			boolean isFirstModifier = true;
1089
			int currentTokenStartPosition = this.scanner.currentPosition;
1090
			boolean hasComment = false;
1091
			while ((this.currentToken = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
1092
				switch(this.currentToken) {
1093
					case TerminalTokens.TokenNamepublic :
1094
					case TerminalTokens.TokenNameprotected :
1095
					case TerminalTokens.TokenNameprivate :
1096
					case TerminalTokens.TokenNamestatic :
1097
					case TerminalTokens.TokenNameabstract :
1098
					case TerminalTokens.TokenNamefinal :
1099
					case TerminalTokens.TokenNamenative :
1100
					case TerminalTokens.TokenNamesynchronized :
1101
					case TerminalTokens.TokenNametransient :
1102
					case TerminalTokens.TokenNamevolatile :
1103
					case TerminalTokens.TokenNamestrictfp :
1104
						this.print(this.scanner.getRawTokenSource(), !isFirstModifier);
1105
						isFirstModifier = false;
1106
						currentTokenStartPosition = this.scanner.currentPosition;
1107
						modifiersIndex++;
1108
						break;
1109
					case TerminalTokens.TokenNameAT :
1110
						if (!isFirstModifier) {
1111
							this.space();
1112
						}
1113
						this.scanner.resetTo(this.scanner.getCurrentTokenStartPosition(), this.scannerEndPosition - 1);
1114
						((Annotation) modifiers.get(modifiersIndex)).accept(visitor);
1115
						if (this.formatter.preferences.insert_new_line_after_annotation) {
1116
							this.printNewLine();
1117
						}
1118
						isFirstModifier = false;
1119
						currentTokenStartPosition = this.scanner.currentPosition;
1120
						modifiersIndex++;
1121
						break;
1122
					case TerminalTokens.TokenNameCOMMENT_BLOCK :
1123
						this.printBlockComment(this.scanner.getRawTokenSource(), false);
1124
						currentTokenStartPosition = this.scanner.currentPosition;
1125
						hasComment = true;
1126
						break;
1127
					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
1128
						this.printBlockComment(this.scanner.getRawTokenSource(), true);
1129
						currentTokenStartPosition = this.scanner.currentPosition;
1130
						hasComment = true;
1131
						break;
1132
					case TerminalTokens.TokenNameCOMMENT_LINE :
1133
						this.printCommentLine(this.scanner.getRawTokenSource());
1134
						currentTokenStartPosition = this.scanner.currentPosition;
1135
						break;
1136
					case TerminalTokens.TokenNameWHITESPACE :
1137
						addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
1138
						int count = 0;
1139
						char[] whiteSpaces = this.scanner.getCurrentTokenSource();
1140
						for (int i = 0, max = whiteSpaces.length; i < max; i++) {
1141
							switch(whiteSpaces[i]) {
1142
								case '\r' :
1143
									if ((i + 1) < max) {
1144
										if (whiteSpaces[i + 1] == '\n') {
1145
											i++;
1146
										}
1147
									}
1148
									count++;
1149
									break;
1150
								case '\n' :
1151
									count++;
1152
							}
1153
						}
1154
						if (count >= 1 && hasComment) {
1155
							printNewLine();
1156
						}
1157
						currentTokenStartPosition = this.scanner.currentPosition;
1158
						hasComment = false;
1159
						break;
1160
					default:
1161
						// step back one token
1162
						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
1163
						return;					
1164
				}
1165
			}
1166
		} catch (InvalidInputException e) {
1167
			throw new AbortFormatting(e);
1168
		}
1169
	}
1170
	
1171
	public void printNewLine() {
1172
		if (this.nlsTagCounter > 0) {
1173
			return;
1174
		}
1175
		if (lastNumberOfNewLines >= 1) {
1176
			column = 1; // ensure that the scribe is at the beginning of a new line
1177
			return;
1178
		}
1179
		addInsertEdit(this.scanner.getCurrentTokenEndPosition() + 1, this.lineSeparator);
1180
		line++;
1181
		lastNumberOfNewLines = 1;
1182
		column = 1;
1183
		needSpace = false;
1184
		this.pendingSpace = false;
1185
	}
1186
1187
	public void printNewLine(int insertPosition) {
1188
		if (this.nlsTagCounter > 0) {
1189
			return;
1190
		}
1191
		if (lastNumberOfNewLines >= 1) {
1192
			column = 1; // ensure that the scribe is at the beginning of a new line
1193
			return;
1194
		}
1195
		addInsertEdit(insertPosition, this.lineSeparator);
1196
		line++;
1197
		lastNumberOfNewLines = 1;
1198
		column = 1;
1199
		needSpace = false;
1200
		this.pendingSpace = false;
1201
	}
1202
1203
	public void printNextToken(int expectedTokenType){
1204
		printNextToken(expectedTokenType, false);
1205
	}
1206
1207
	public void printNextToken(int expectedTokenType, boolean considerSpaceIfAny){
1208
		printComment();
1209
		try {
1210
			this.currentToken = this.scanner.getNextToken();
1211
			char[] currentTokenSource = this.scanner.getRawTokenSource();
1212
			if (expectedTokenType != this.currentToken) {
1213
				throw new AbortFormatting("unexpected token type, expecting:"+expectedTokenType+", actual:"+this.currentToken);//$NON-NLS-1$//$NON-NLS-2$
1214
			}
1215
			this.print(currentTokenSource, considerSpaceIfAny);
1216
		} catch (InvalidInputException e) {
1217
			throw new AbortFormatting(e);
1218
		}
1219
	}
1220
1221
	public void printNextToken(int[] expectedTokenTypes) {
1222
		printNextToken(expectedTokenTypes, false);
1223
	}
1224
1225
	public void printNextToken(int[] expectedTokenTypes, boolean considerSpaceIfAny){
1226
		printComment();
1227
		try {
1228
			this.currentToken = this.scanner.getNextToken();
1229
			char[] currentTokenSource = this.scanner.getRawTokenSource();
1230
			if (Arrays.binarySearch(expectedTokenTypes, this.currentToken) < 0) {
1231
				StringBuffer expectations = new StringBuffer(5);
1232
				for (int i = 0; i < expectedTokenTypes.length; i++){
1233
					if (i > 0) {
1234
						expectations.append(',');
1235
					}
1236
					expectations.append(expectedTokenTypes[i]);
1237
				}				
1238
				throw new AbortFormatting("unexpected token type, expecting:["+expectations.toString()+"], actual:"+this.currentToken);//$NON-NLS-1$//$NON-NLS-2$
1239
			}
1240
			this.print(currentTokenSource, considerSpaceIfAny);
1241
		} catch (InvalidInputException e) {
1242
			throw new AbortFormatting(e);
1243
		}
1244
	}
1245
1246
	public void printArrayQualifiedReference(int numberOfTokens, int sourceEnd) {
1247
		int currentTokenStartPosition = this.scanner.currentPosition;
1248
		int numberOfIdentifiers = 0;
1249
		try {
1250
			do {
1251
				this.printComment();
1252
				switch(this.currentToken = this.scanner.getNextToken()) {
1253
					case TerminalTokens.TokenNameEOF :
1254
						return;
1255
					case TerminalTokens.TokenNameWHITESPACE :
1256
						addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
1257
						currentTokenStartPosition = this.scanner.currentPosition;
1258
						break;
1259
					case TerminalTokens.TokenNameCOMMENT_BLOCK :
1260
					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
1261
						this.printBlockComment(this.scanner.getRawTokenSource(), false);
1262
						currentTokenStartPosition = this.scanner.currentPosition;
1263
						break;
1264
					case TerminalTokens.TokenNameCOMMENT_LINE :
1265
						this.printCommentLine(this.scanner.getRawTokenSource());
1266
						currentTokenStartPosition = this.scanner.currentPosition;
1267
						break;
1268
					case TerminalTokens.TokenNameIdentifier :
1269
						this.print(this.scanner.getRawTokenSource(), false);
1270
						currentTokenStartPosition = this.scanner.currentPosition;
1271
						if (++ numberOfIdentifiers == numberOfTokens) {
1272
							this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
1273
							return;
1274
						}
1275
						break;						
1276
					case TerminalTokens.TokenNameDOT :
1277
						this.print(this.scanner.getRawTokenSource(), false);
1278
						currentTokenStartPosition = this.scanner.currentPosition;
1279
						break;
1280
					default:
1281
						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
1282
						return;
1283
				}
1284
			} while (this.scanner.currentPosition <= sourceEnd);
1285
		} catch(InvalidInputException e) {
1286
			throw new AbortFormatting(e);
1287
		}
1288
	}
1289
/*
1290
	public void printQualifiedReference(Name name) {
1291
		final int sourceEnd = name.getStartPosition() + name.getLength() - 1;
1292
		int currentTokenStartPosition = this.scanner.currentPosition;
1293
		try {
1294
			do {
1295
				this.printComment();
1296
				switch(this.currentToken = this.scanner.getNextToken()) {
1297
					case TerminalTokens.TokenNameEOF :
1298
						return;
1299
					case TerminalTokens.TokenNameWHITESPACE :
1300
						addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
1301
						currentTokenStartPosition = this.scanner.currentPosition;
1302
						break;
1303
					case TerminalTokens.TokenNameCOMMENT_BLOCK :
1304
					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
1305
						this.printBlockComment(this.scanner.getRawTokenSource(), false);
1306
						currentTokenStartPosition = this.scanner.currentPosition;
1307
						break;
1308
					case TerminalTokens.TokenNameCOMMENT_LINE :
1309
						this.printCommentLine(this.scanner.getRawTokenSource());
1310
						currentTokenStartPosition = this.scanner.currentPosition;
1311
						break;
1312
					case TerminalTokens.TokenNameIdentifier :
1313
					case TerminalTokens.TokenNameDOT :
1314
						this.print(this.scanner.getRawTokenSource(), false);
1315
						currentTokenStartPosition = this.scanner.currentPosition;
1316
						break;
1317
					default:
1318
						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
1319
						return;
1320
				}
1321
			} while (this.scanner.currentPosition <= sourceEnd);
1322
		} catch(InvalidInputException e) {
1323
			throw new AbortFormatting(e);
1324
		}
1325
	}
1326
*/
1327
	private void printRule(StringBuffer stringBuffer) {
1328
		for (int i = 0; i < this.pageWidth; i++){
1329
			if ((i % this.tabLength) == 0) { 
1330
				stringBuffer.append('+');
1331
			} else {
1332
				stringBuffer.append('-');
1333
			}
1334
		}
1335
		stringBuffer.append(this.lineSeparator);
1336
		
1337
		for (int i = 0; i < (pageWidth / tabLength); i++) {
1338
			stringBuffer.append(i);
1339
			stringBuffer.append('\t');
1340
		}			
1341
	}
1342
1343
	public void printTrailingComment() {
1344
		try {
1345
			// if we have a space between two tokens we ensure it will be dumped in the formatted string
1346
			int currentTokenStartPosition = this.scanner.currentPosition;
1347
			boolean hasWhitespaces = false;
1348
			boolean hasComment = false;
1349
			boolean hasLineComment = false;
1350
			while ((this.currentToken = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
1351
				switch(this.currentToken) {
1352
					case TerminalTokens.TokenNameWHITESPACE :
1353
						int count = 0;
1354
						char[] whiteSpaces = this.scanner.getCurrentTokenSource();
1355
						for (int i = 0, max = whiteSpaces.length; i < max; i++) {
1356
							switch(whiteSpaces[i]) {
1357
								case '\r' :
1358
									if ((i + 1) < max) {
1359
										if (whiteSpaces[i + 1] == '\n') {
1360
											i++;
1361
										}
1362
									}
1363
									count++;
1364
									break;
1365
								case '\n' :
1366
									count++;
1367
							}
1368
						}
1369
						if (hasLineComment) {
1370
							if (count >= 1) {
1371
								currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition();
1372
								this.preserveEmptyLines(count, currentTokenStartPosition);
1373
								addDeleteEdit(currentTokenStartPosition, this.scanner.getCurrentTokenEndPosition());
1374
								this.scanner.resetTo(this.scanner.currentPosition, this.scannerEndPosition - 1);
1375
								return;
1376
							} else {
1377
								this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
1378
								return;
1379
							}
1380
						} else if (count >= 1) {
1381
							if (hasComment) {
1382
								this.printNewLine(this.scanner.getCurrentTokenStartPosition());
1383
							}
1384
							this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
1385
							return;
1386
						} else {
1387
							hasWhitespaces = true;
1388
							currentTokenStartPosition = this.scanner.currentPosition;						
1389
							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
1390
						}
1391
						break;
1392
					case TerminalTokens.TokenNameCOMMENT_LINE :
1393
						if (hasWhitespaces) {
1394
							space();
1395
						}
1396
						this.printCommentLine(this.scanner.getRawTokenSource());
1397
						currentTokenStartPosition = this.scanner.currentPosition;
1398
						hasLineComment = true;
1399
						break;
1400
					case TerminalTokens.TokenNameCOMMENT_BLOCK :
1401
						if (hasWhitespaces) {
1402
							space();
1403
						}
1404
						this.printBlockComment(this.scanner.getRawTokenSource(), false);
1405
						currentTokenStartPosition = this.scanner.currentPosition;
1406
						hasComment = true;
1407
						break;
1408
					default :
1409
						// step back one token
1410
						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
1411
						return;
1412
				}
1413
			}
1414
		} catch (InvalidInputException e) {
1415
			throw new AbortFormatting(e);
1416
		}
1417
	}
1418
1419
	void redoAlignment(AlignmentException e){
1420
		if (e.relativeDepth > 0) { // if exception targets a distinct context
1421
			e.relativeDepth--; // record fact that current context got traversed
1422
			this.currentAlignment = this.currentAlignment.enclosing; // pop currentLocation
1423
			throw e; // rethrow
1424
		} 
1425
		// reset scribe/scanner to restart at this given location
1426
		this.resetAt(this.currentAlignment.location);
1427
		this.scanner.resetTo(this.currentAlignment.location.inputOffset, this.scanner.eofPosition);
1428
		// clean alignment chunkKind so it will think it is a new chunk again
1429
		this.currentAlignment.chunkKind = 0;
1430
	}
1431
1432
	void redoMemberAlignment(AlignmentException e){
1433
		// reset scribe/scanner to restart at this given location
1434
		this.resetAt(this.memberAlignment.location);
1435
		this.scanner.resetTo(this.memberAlignment.location.inputOffset, this.scanner.eofPosition);
1436
		// clean alignment chunkKind so it will think it is a new chunk again
1437
		this.memberAlignment.chunkKind = 0;
1438
	}
1439
1440
	public void reset() {
1441
		this.checkLineWrapping = true;
1442
		this.line = 0;
1443
		this.column = 1;
1444
		this.editsIndex = 0;
1445
		this.nlsTagCounter = 0;
1446
	}
1447
		
1448
	private void resetAt(Location2 location) {
1449
		this.line = location.outputLine;
1450
		this.column = location.outputColumn;
1451
		this.indentationLevel = location.outputIndentationLevel;
1452
		this.numberOfIndentations = location.numberOfIndentations;
1453
		this.lastNumberOfNewLines = location.lastNumberOfNewLines;
1454
		this.needSpace = location.needSpace;
1455
		this.pendingSpace = location.pendingSpace;
1456
		this.editsIndex = location.editsIndex;
1457
		this.nlsTagCounter = location.nlsTagCounter;
1458
		if (this.editsIndex > 0) {
1459
			this.edits[this.editsIndex - 1] = location.textEdit;
1460
		}
1461
	}
1462
1463
	private void resize() {
1464
		System.arraycopy(this.edits, 0, (this.edits = new OptimizedReplaceEdit[this.editsIndex * 2]), 0, this.editsIndex);
1465
	}
1466
1467
	public void space() {
1468
		if (!this.needSpace) return;
1469
		this.lastNumberOfNewLines = 0;
1470
		this.pendingSpace = true;
1471
		this.column++;
1472
		this.needSpace = false;		
1473
	}
1474
1475
	public String toString() {
1476
		StringBuffer stringBuffer = new StringBuffer();
1477
		stringBuffer
1478
			.append("(page width = " + this.pageWidth + ") - (tabChar = ");//$NON-NLS-1$//$NON-NLS-2$
1479
		switch(this.tabChar) {
1480
			case DefaultCodeFormatterOptions.TAB :
1481
				 stringBuffer.append("TAB");//$NON-NLS-1$
1482
				 break;
1483
			case DefaultCodeFormatterOptions.SPACE :
1484
				 stringBuffer.append("SPACE");//$NON-NLS-1$
1485
				 break;
1486
			default :
1487
				 stringBuffer.append("MIXED");//$NON-NLS-1$
1488
		}
1489
		stringBuffer
1490
			.append(") - (tabSize = " + this.tabLength + ")")//$NON-NLS-1$//$NON-NLS-2$
1491
			.append(this.lineSeparator)
1492
			.append("(line = " + this.line + ") - (column = " + this.column + ") - (identationLevel = " + this.indentationLevel + ")")	//$NON-NLS-1$	//$NON-NLS-2$	//$NON-NLS-3$	//$NON-NLS-4$
1493
			.append(this.lineSeparator)
1494
			.append("(needSpace = " + this.needSpace + ") - (lastNumberOfNewLines = " + this.lastNumberOfNewLines + ") - (checkLineWrapping = " + this.checkLineWrapping + ")")	//$NON-NLS-1$	//$NON-NLS-2$	//$NON-NLS-3$	//$NON-NLS-4$
1495
			.append(this.lineSeparator)
1496
			.append("==================================================================================")	//$NON-NLS-1$
1497
			.append(this.lineSeparator);
1498
		printRule(stringBuffer);
1499
		return stringBuffer.toString();
1500
	}
1501
	
1502
	public void unIndent() {
1503
		this.indentationLevel -= this.indentationSize;
1504
		this.numberOfIndentations--;
1505
	}
1506
}
(-)formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java (-16 / +40 lines)
Lines 96-103 Link Here
96
	public int blank_lines_between_type_declarations;
96
	public int blank_lines_between_type_declarations;
97
	public int blank_lines_at_beginning_of_method_body;
97
	public int blank_lines_at_beginning_of_method_body;
98
	
98
	
99
	public boolean comment_clear_blank_lines;
99
	public boolean comment_clear_blank_lines_in_javadoc_comment;
100
	public boolean comment_format;
100
	public boolean comment_clear_blank_lines_in_block_comment;
101
	public boolean comment_format_javadoc_comment;
102
	public boolean comment_format_line_comment;
103
	public boolean comment_format_block_comment;
101
	public boolean comment_format_header;
104
	public boolean comment_format_header;
102
	public boolean comment_format_html;
105
	public boolean comment_format_html;
103
	public boolean comment_format_source;
106
	public boolean comment_format_source;
Lines 353-360 Link Here
353
		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION, this.brace_position_for_method_declaration);
356
		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION, this.brace_position_for_method_declaration);
354
		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION, this.brace_position_for_type_declaration);
357
		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION, this.brace_position_for_type_declaration);
355
		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_SWITCH, this.brace_position_for_switch);
358
		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_SWITCH, this.brace_position_for_switch);
356
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES, this.comment_clear_blank_lines ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
359
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_BLOCK_COMMENT, this.comment_clear_blank_lines_in_javadoc_comment ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
357
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT, this.comment_format ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
360
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_JAVADOC_COMMENT, this.comment_clear_blank_lines_in_block_comment ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
361
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT, this.comment_format_javadoc_comment ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
362
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_LINE_COMMENT, this.comment_format_line_comment ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
363
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT, this.comment_format_block_comment ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
358
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HEADER, this.comment_format_header ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
364
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HEADER, this.comment_format_header ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
359
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HTML, this.comment_format_html ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
365
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HTML, this.comment_format_html ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
360
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_SOURCE, this.comment_format_source ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
366
		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_SOURCE, this.comment_format_source ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
Lines 1015-1028 Link Here
1015
				this.blank_lines_at_beginning_of_method_body = 0;
1021
				this.blank_lines_at_beginning_of_method_body = 0;
1016
			}
1022
			}
1017
		}
1023
		}
1018
		final Object commentClearBlankLinesOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES);
1024
		final Object commentClearBlankLinesInJavadocCommentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_JAVADOC_COMMENT);
1019
		if (commentClearBlankLinesOption != null) {
1025
		if (commentClearBlankLinesInJavadocCommentOption != null) {
1020
			this.comment_clear_blank_lines = DefaultCodeFormatterConstants.TRUE.equals(commentClearBlankLinesOption);
1026
			this.comment_clear_blank_lines_in_javadoc_comment = DefaultCodeFormatterConstants.TRUE.equals(commentClearBlankLinesInJavadocCommentOption);
1021
		}
1027
		}
1022
		final Object commentFormatOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT);
1028
		final Object commentClearBlankLinesInBlockCommentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_BLOCK_COMMENT);
1023
		if (commentFormatOption != null) {
1029
		if (commentClearBlankLinesInBlockCommentOption != null) {
1024
			this.comment_format = DefaultCodeFormatterConstants.TRUE.equals(commentFormatOption);
1030
			this.comment_clear_blank_lines_in_block_comment = DefaultCodeFormatterConstants.TRUE.equals(commentClearBlankLinesInBlockCommentOption);
1025
		}
1031
		}
1032
		final Object commentFormatJavadocCommentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT);
1033
		if (commentFormatJavadocCommentOption != null) {
1034
			this.comment_format_javadoc_comment = DefaultCodeFormatterConstants.TRUE.equals(commentFormatJavadocCommentOption);
1035
		}
1036
		final Object commentFormatBlockCommentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT);
1037
		if (commentFormatBlockCommentOption != null) {
1038
			this.comment_format_block_comment = DefaultCodeFormatterConstants.TRUE.equals(commentFormatBlockCommentOption);
1039
		}
1040
		final Object commentFormatLineCommentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_LINE_COMMENT);
1041
		if (commentFormatLineCommentOption != null) {
1042
			this.comment_format_line_comment = DefaultCodeFormatterConstants.TRUE.equals(commentFormatLineCommentOption);
1043
		}		
1026
		final Object commentFormatHeaderOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HEADER);
1044
		final Object commentFormatHeaderOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HEADER);
1027
		if (commentFormatHeaderOption != null) {
1045
		if (commentFormatHeaderOption != null) {
1028
			this.comment_format_header = DefaultCodeFormatterConstants.TRUE.equals(commentFormatHeaderOption);
1046
			this.comment_format_header = DefaultCodeFormatterConstants.TRUE.equals(commentFormatHeaderOption);
Lines 1894-1901 Link Here
1894
		this.brace_position_for_method_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
1912
		this.brace_position_for_method_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
1895
		this.brace_position_for_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
1913
		this.brace_position_for_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
1896
		this.brace_position_for_switch = DefaultCodeFormatterConstants.END_OF_LINE;
1914
		this.brace_position_for_switch = DefaultCodeFormatterConstants.END_OF_LINE;
1897
		this.comment_clear_blank_lines = false;
1915
		this.comment_clear_blank_lines_in_block_comment = false;
1898
		this.comment_format = true;
1916
		this.comment_clear_blank_lines_in_javadoc_comment = false;
1917
		this.comment_format_block_comment = true;
1918
		this.comment_format_javadoc_comment = true;
1919
		this.comment_format_line_comment = true;
1899
		this.comment_format_header = false;
1920
		this.comment_format_header = false;
1900
		this.comment_format_html = true;
1921
		this.comment_format_html = true;
1901
		this.comment_format_source = true;
1922
		this.comment_format_source = true;
Lines 2150-2157 Link Here
2150
		this.brace_position_for_method_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
2171
		this.brace_position_for_method_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
2151
		this.brace_position_for_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
2172
		this.brace_position_for_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
2152
		this.brace_position_for_switch = DefaultCodeFormatterConstants.END_OF_LINE;
2173
		this.brace_position_for_switch = DefaultCodeFormatterConstants.END_OF_LINE;
2153
		this.comment_clear_blank_lines = false;
2174
		this.comment_clear_blank_lines_in_block_comment = false;
2154
		this.comment_format = true;
2175
		this.comment_clear_blank_lines_in_javadoc_comment = false;
2176
		this.comment_format_block_comment = true;
2177
		this.comment_format_javadoc_comment = true;
2178
		this.comment_format_line_comment = true;
2155
		this.comment_format_header = false;
2179
		this.comment_format_header = false;
2156
		this.comment_format_html = true;
2180
		this.comment_format_html = true;
2157
		this.comment_format_source = true;
2181
		this.comment_format_source = true;
(-)model/org/eclipse/jdt/internal/core/JavaModelManager.java (-6 lines)
Lines 60-66 Link Here
60
import org.eclipse.jdt.internal.core.util.Util;
60
import org.eclipse.jdt.internal.core.util.Util;
61
import org.eclipse.jdt.internal.core.util.WeakHashSet;
61
import org.eclipse.jdt.internal.core.util.WeakHashSet;
62
import org.eclipse.jdt.internal.core.util.WeakHashSetOfCharArray;
62
import org.eclipse.jdt.internal.core.util.WeakHashSetOfCharArray;
63
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
64
import org.osgi.service.prefs.BackingStoreException;
63
import org.osgi.service.prefs.BackingStoreException;
65
import org.w3c.dom.Element;
64
import org.w3c.dom.Element;
66
import org.w3c.dom.Node;
65
import org.w3c.dom.Node;
Lines 194-201 Link Here
194
	public static final String CONTAINER_INITIALIZER_PERF = JavaCore.PLUGIN_ID + "/perf/containerinitializer" ; //$NON-NLS-1$
193
	public static final String CONTAINER_INITIALIZER_PERF = JavaCore.PLUGIN_ID + "/perf/containerinitializer" ; //$NON-NLS-1$
195
	public static final String RECONCILE_PERF = JavaCore.PLUGIN_ID + "/perf/reconcile" ; //$NON-NLS-1$
194
	public static final String RECONCILE_PERF = JavaCore.PLUGIN_ID + "/perf/reconcile" ; //$NON-NLS-1$
196
	
195
	
197
	private static final String ENABLE_NEW_FORMATTER = JavaCore.PLUGIN_ID + "/formatter/enable_new" ; //$NON-NLS-1$
198
199
	private final static String INDEXED_SECONDARY_TYPES = "#@*_indexing secondary cache_*@#"; //$NON-NLS-1$
196
	private final static String INDEXED_SECONDARY_TYPES = "#@*_indexing secondary cache_*@#"; //$NON-NLS-1$
200
197
201
	public static boolean PERF_VARIABLE_INITIALIZER = false;
198
	public static boolean PERF_VARIABLE_INITIALIZER = false;
Lines 1263-1271 Link Here
1263
			
1260
			
1264
			option = Platform.getDebugOption(SOURCE_MAPPER_DEBUG_VERBOSE);
1261
			option = Platform.getDebugOption(SOURCE_MAPPER_DEBUG_VERBOSE);
1265
			if(option != null) SourceMapper.VERBOSE = option.equalsIgnoreCase(TRUE) ;
1262
			if(option != null) SourceMapper.VERBOSE = option.equalsIgnoreCase(TRUE) ;
1266
			
1267
			option = Platform.getDebugOption(ENABLE_NEW_FORMATTER);
1268
			if(option != null) DefaultCodeFormatter.USE_NEW_FORMATTER = option.equalsIgnoreCase(TRUE) ;
1269
		}
1263
		}
1270
		
1264
		
1271
		// configure performance options
1265
		// configure performance options
(-)formatter/org/eclipse/jdt/internal/formatter/comment/MultiCommentRegion.java (+1 lines)
Lines 52-57 Link Here
52
		fIndentDescriptions= this.preferences.comment_indent_parameter_description;
52
		fIndentDescriptions= this.preferences.comment_indent_parameter_description;
53
		fSeparateRoots= this.preferences.comment_insert_empty_line_before_root_tags;
53
		fSeparateRoots= this.preferences.comment_insert_empty_line_before_root_tags;
54
		fParameterNewLine= this.preferences.comment_insert_new_line_for_parameter;
54
		fParameterNewLine= this.preferences.comment_insert_new_line_for_parameter;
55
		fClear = this.preferences.comment_clear_blank_lines_in_block_comment;
55
	}
56
	}
56
57
57
	/*
58
	/*
(-)formatter/org/eclipse/jdt/internal/formatter/comment/JavaDocRegion.java (-2 / +3 lines)
Lines 56-63 Link Here
56
	public JavaDocRegion(final IDocument document, final Position position, final CodeFormatterVisitor formatter) {
56
	public JavaDocRegion(final IDocument document, final Position position, final CodeFormatterVisitor formatter) {
57
		super(document, position, formatter);
57
		super(document, position, formatter);
58
58
59
		fFormatSource= this.preferences.comment_format_source;
59
		fFormatSource = this.preferences.comment_format_source;
60
		fFormatHtml= this.preferences.comment_format_html;
60
		fFormatHtml = this.preferences.comment_format_html;
61
		fClear = this.preferences.comment_clear_blank_lines_in_javadoc_comment;
61
	}
62
	}
62
63
63
	/*
64
	/*
(-)formatter/org/eclipse/jdt/internal/formatter/comment/CommentRegion.java (-3 / +1 lines)
Lines 48-54 Link Here
48
	private int fBorders= 0;
48
	private int fBorders= 0;
49
49
50
	/** Should all blank lines be cleared during formatting? */
50
	/** Should all blank lines be cleared during formatting? */
51
	private final boolean fClear;
51
	protected boolean fClear;
52
52
53
	/** The line delimiter used in this comment region */
53
	/** The line delimiter used in this comment region */
54
	private final String fDelimiter;
54
	private final String fDelimiter;
Lines 88-95 Link Here
88
		fDelimiter = this.preferences.line_separator;
88
		fDelimiter = this.preferences.line_separator;
89
		fDocument= document;
89
		fDocument= document;
90
		
90
		
91
		fClear= this.preferences.comment_clear_blank_lines;
92
		
93
		fTabSize= DefaultCodeFormatterOptions.SPACE == this.preferences.tab_char ? this.preferences.indentation_size : this.preferences.tab_size;
91
		fTabSize= DefaultCodeFormatterOptions.SPACE == this.preferences.tab_char ? this.preferences.indentation_size : this.preferences.tab_size;
94
92
95
		this.scribe = formatter.scribe;
93
		this.scribe = formatter.scribe;
(-)formatter/org/eclipse/jdt/internal/formatter/align/Alignment2.java (-417 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.formatter.align;
12
13
import org.eclipse.jdt.internal.formatter.Location2;
14
import org.eclipse.jdt.internal.formatter.Scribe2;
15
16
/**
17
 * Alignment management
18
 * 
19
 * @since 2.1
20
 */
21
public class Alignment2 {
22
23
	// name of alignment
24
	public String name;
25
	
26
	// link to enclosing alignment
27
	public Alignment2 enclosing;
28
	 
29
	// start location of this alignment
30
	public Location2 location;
31
	
32
	// indentation management
33
	public int fragmentIndex;
34
	public int fragmentCount;
35
	public int[] fragmentIndentations;
36
	public boolean needRedoColumnAlignment;
37
38
	// chunk management
39
	public int chunkStartIndex;
40
	public int chunkKind;
41
42
	// break management	
43
	public int originalIndentationLevel;
44
	public int breakIndentationLevel;
45
	public int shiftBreakIndentationLevel;
46
	public int[] fragmentBreaks;
47
	public boolean wasSplit;
48
49
	public Scribe2 scribe;
50
	
51
	/* 
52
	 * Alignment modes
53
	 */
54
	public static final int M_FORCE = 1; // if bit set, then alignment will be non-optional (default is optional)
55
	public static final int M_INDENT_ON_COLUMN = 2; // if bit set, broken fragments will be aligned on current location column (default is to break at current indentation level)
56
	public static final int	M_INDENT_BY_ONE = 4; // if bit set, broken fragments will be indented one level below current (not using continuation indentation)
57
58
	// split modes can be combined either with M_FORCE or M_INDENT_ON_COLUMN
59
	
60
	/** foobar(#fragment1, #fragment2, <ul>
61
	 *  <li>    #fragment3, #fragment4 </li>
62
	 * </ul>
63
	 */
64
	public static final int M_COMPACT_SPLIT = 16; // fill each line with all possible fragments
65
66
	/** foobar(<ul>
67
	 * <li>    #fragment1, #fragment2,  </li>
68
	 * <li>     #fragment5, #fragment4, </li>
69
	 * </ul>
70
	 */
71
	public static final int M_COMPACT_FIRST_BREAK_SPLIT = 32; //  compact mode, but will first try to break before first fragment
72
73
	/** foobar(<ul>
74
	 * <li>     #fragment1,  </li>
75
	 * <li>     #fragment2,  </li>
76
	 * <li>     #fragment3 </li>
77
	 * <li>     #fragment4,  </li>
78
	 * </ul>
79
	 */
80
	public static final int M_ONE_PER_LINE_SPLIT = 32+16; // one fragment per line
81
82
	/** 
83
	 * foobar(<ul>
84
	 * <li>     #fragment1,  </li>
85
	 * <li>        #fragment2,  </li>
86
	 * <li>        #fragment3 </li>
87
	 * <li>        #fragment4,  </li>
88
	 * </ul>
89
	 */ 
90
	public static final int M_NEXT_SHIFTED_SPLIT = 64; // one fragment per line, subsequent are indented further
91
92
	/** foobar(#fragment1, <ul>
93
	 * <li>      #fragment2,  </li>
94
	 * <li>      #fragment3 </li>
95
	 * <li>      #fragment4,  </li>
96
	 * </ul>
97
	 */
98
	public static final int M_NEXT_PER_LINE_SPLIT = 64+16; // one per line, except first fragment (if possible)
99
100
	//64+32
101
	//64+32+16
102
	
103
	// mode controlling column alignments
104
	/** 
105
	 * <table BORDER COLS=4 WIDTH="100%" >
106
	 * <tr><td>#fragment1A</td>            <td>#fragment2A</td>       <td>#fragment3A</td>  <td>#very-long-fragment4A</td></tr>
107
	 * <tr><td>#fragment1B</td>            <td>#long-fragment2B</td>  <td>#fragment3B</td>  <td>#fragment4B</td></tr>
108
	 * <tr><td>#very-long-fragment1C</td>  <td>#fragment2C</td>       <td>#fragment3C</td>  <td>#fragment4C</td></tr>
109
	 * </table>
110
	 */
111
	public static final int M_MULTICOLUMN = 256; // fragments are on same line, but multiple line of fragments will be aligned vertically
112
	
113
	public static final int M_NO_ALIGNMENT = 0;
114
	
115
	public int mode;
116
	
117
	public static final int SPLIT_MASK = M_ONE_PER_LINE_SPLIT | M_NEXT_SHIFTED_SPLIT | M_COMPACT_SPLIT | M_COMPACT_FIRST_BREAK_SPLIT | M_NEXT_PER_LINE_SPLIT;
118
119
	// alignment tie-break rules - when split is needed, will decide whether innermost/outermost alignment is to be chosen
120
	public static final int R_OUTERMOST = 1;
121
	public static final int R_INNERMOST = 2;
122
	public int tieBreakRule;
123
	
124
	// alignment effects on a per fragment basis
125
	public static final int NONE = 0;
126
	public static final int BREAK = 1;
127
	
128
	// chunk kind
129
	public static final int CHUNK_FIELD = 1;
130
	public static final int CHUNK_METHOD = 2;
131
	public static final int CHUNK_TYPE = 3;
132
	public static final int CHUNK_ENUM = 4;
133
134
	// location to align and break on.
135
	public Alignment2(String name, int mode, int tieBreakRule, Scribe2 scribe, int fragmentCount, int sourceRestart, int continuationIndent){
136
		
137
		this.name = name;
138
		this.location = new Location2(scribe, sourceRestart);
139
		this.mode = mode;
140
		this.tieBreakRule = tieBreakRule;
141
		this.fragmentCount = fragmentCount;
142
		this.scribe = scribe;
143
		this.originalIndentationLevel = this.scribe.indentationLevel;
144
		this.wasSplit = false;
145
		
146
		// initialize the break indentation level, using modes and continuationIndentationLevel preference
147
		final int indentSize = this.scribe.indentationSize;
148
		int currentColumn = this.location.outputColumn;
149
		if (currentColumn == 1) {
150
		    currentColumn = this.location.outputIndentationLevel + 1;
151
		}
152
		
153
		if ((mode & M_INDENT_ON_COLUMN) != 0) {
154
			// indent broken fragments at next indentation level, based on current column
155
			this.breakIndentationLevel = this.scribe.getNextIndentationLevel(currentColumn);
156
			if (this.breakIndentationLevel == this.location.outputIndentationLevel) {
157
				this.breakIndentationLevel += (continuationIndent * indentSize);
158
			}
159
		} else if ((mode & M_INDENT_BY_ONE) != 0) {
160
			// indent broken fragments exactly one level deeper than current indentation
161
			this.breakIndentationLevel = this.location.outputIndentationLevel + indentSize;
162
		} else {
163
			this.breakIndentationLevel = this.location.outputIndentationLevel + continuationIndent * indentSize;
164
		}
165
		this.shiftBreakIndentationLevel = this.breakIndentationLevel + indentSize;
166
167
		this.fragmentIndentations = new int[this.fragmentCount];
168
		this.fragmentBreaks = new int[this.fragmentCount];
169
170
		// check for forced alignments
171
		if ((this.mode & M_FORCE) != 0) {
172
			couldBreak();
173
		}					
174
	}
175
	
176
	public boolean checkChunkStart(int kind, int startIndex, int sourceRestart) {
177
		if (this.chunkKind != kind) {
178
			this.chunkKind = kind;
179
			
180
			// when redoing same chunk alignment, must not reset
181
			if (startIndex != this.chunkStartIndex) {
182
				this.chunkStartIndex = startIndex;
183
				this.location.update(this.scribe, sourceRestart);
184
				reset();
185
			}
186
			return true;
187
		}
188
		return false;
189
	}
190
191
	public void checkColumn() {
192
		if ((this.mode & M_MULTICOLUMN) != 0) {
193
			int currentIndentation = this.scribe.getNextIndentationLevel(this.scribe.column+(this.scribe.needSpace ? 1 : 0));
194
			int fragmentIndentation = this.fragmentIndentations[this.fragmentIndex];
195
			if (currentIndentation > fragmentIndentation) {
196
				this.fragmentIndentations[this.fragmentIndex] =  currentIndentation;
197
				if (fragmentIndentation != 0) {
198
					for (int i = this.fragmentIndex+1; i < this.fragmentCount; i++) {
199
						this.fragmentIndentations[i] = 0;
200
					}
201
					this.needRedoColumnAlignment = true;
202
				}
203
			}
204
			// backtrack only once all fragments got checked
205
			if (this.needRedoColumnAlignment && this.fragmentIndex == this.fragmentCount-1) { // alignment too small
206
207
//				if (CodeFormatterVisitor.DEBUG){
208
//					System.out.println("ALIGNMENT TOO SMALL");
209
//					System.out.println(this);
210
//				}
211
				this.needRedoColumnAlignment = false;
212
				int relativeDepth = 0;
213
				Alignment2 targetAlignment = this.scribe.memberAlignment;
214
				while (targetAlignment != null){
215
					if (targetAlignment == this){
216
						throw new AlignmentException(AlignmentException.ALIGN_TOO_SMALL, relativeDepth);
217
					}
218
					targetAlignment = targetAlignment.enclosing;
219
					relativeDepth++;
220
				}
221
			}
222
		}
223
	}
224
		
225
	public boolean couldBreak(){
226
		int i;
227
		switch(mode & SPLIT_MASK){
228
229
			/*  # aligned fragment
230
			 *  foo(
231
			 *     #AAAAA, #BBBBB,
232
			 *     #CCCC);
233
			 */
234
			case M_COMPACT_FIRST_BREAK_SPLIT : 
235
				if (this.fragmentBreaks[0] == NONE) {
236
					this.fragmentBreaks[0] = BREAK;
237
					this.fragmentIndentations[0] = this.breakIndentationLevel;
238
					return wasSplit = true;
239
				}
240
				i = this.fragmentIndex;
241
				do {
242
					if (this.fragmentBreaks[i] == NONE) {
243
						this.fragmentBreaks[i] = BREAK;
244
						this.fragmentIndentations[i] = this.breakIndentationLevel;
245
						return wasSplit = true;
246
					}
247
				} while (--i >= 0);
248
				break;
249
			/*  # aligned fragment
250
			 *  foo(#AAAAA, #BBBBB,
251
			 *     #CCCC);
252
			 */
253
			case M_COMPACT_SPLIT :
254
				i = this.fragmentIndex;
255
				do {
256
					if (this.fragmentBreaks[i] == NONE) {
257
						this.fragmentBreaks[i] = BREAK;
258
						this.fragmentIndentations[i] = this.breakIndentationLevel;						
259
						return wasSplit = true;
260
					}
261
				} while (--i >= 0);
262
				break;
263
264
			/*  # aligned fragment
265
			 *  foo(
266
			 *      #AAAAA,
267
			 *          #BBBBB,
268
			 *          #CCCC);
269
			 */
270
			case M_NEXT_SHIFTED_SPLIT :
271
				if (this.fragmentBreaks[0] == NONE) {
272
					this.fragmentBreaks[0] = BREAK;					
273
					this.fragmentIndentations[0] = this.breakIndentationLevel;
274
					for (i = 1; i < this.fragmentCount; i++){
275
						this.fragmentBreaks[i] = BREAK;
276
						this.fragmentIndentations[i] = this.shiftBreakIndentationLevel;
277
					}
278
					return wasSplit = true;
279
				}
280
				break;
281
				
282
			/*  # aligned fragment
283
			 *  foo(
284
			 *      #AAAAA,
285
			 *      #BBBBB,
286
			 *      #CCCC);
287
			 */
288
			case M_ONE_PER_LINE_SPLIT :
289
				if (this.fragmentBreaks[0] == NONE) {
290
					for (i = 0; i < this.fragmentCount; i++){
291
						this.fragmentBreaks[i] = BREAK;
292
						this.fragmentIndentations[i] = this.breakIndentationLevel;
293
					}
294
					return wasSplit = true;
295
				}
296
			/*  # aligned fragment
297
			 *  foo(#AAAAA,
298
			 *      #BBBBB,
299
			 *      #CCCC);
300
			 */
301
			case M_NEXT_PER_LINE_SPLIT : 
302
				if (this.fragmentBreaks[0] == NONE) {
303
					if (this.fragmentCount > 1
304
							&& this.fragmentBreaks[1] == NONE) {
305
						if ((this.mode & M_INDENT_ON_COLUMN) != 0) {
306
							this.fragmentIndentations[0] = this.breakIndentationLevel;
307
						}
308
						for (i = 1; i < this.fragmentCount; i++) {
309
							this.fragmentBreaks[i] = BREAK;
310
							this.fragmentIndentations[i] = this.breakIndentationLevel;
311
						}
312
						return wasSplit = true;
313
					}
314
				}
315
				break;
316
		}		
317
		return false; // cannot split better
318
	}
319
	
320
	public Alignment2 getAlignment(String targetName) {
321
322
		if (targetName.equals(this.name)) return this;
323
		if (this.enclosing == null) return null;
324
		
325
		return this.enclosing.getAlignment(targetName);
326
	}
327
		
328
	// perform alignment effect for current fragment
329
	public void performFragmentEffect(){
330
		if ((this.mode & M_MULTICOLUMN) == 0) {
331
			switch(this.mode & SPLIT_MASK) {
332
				case Alignment2.M_COMPACT_SPLIT :
333
				case Alignment2.M_COMPACT_FIRST_BREAK_SPLIT :
334
				case Alignment2.M_NEXT_PER_LINE_SPLIT :
335
				case Alignment2.M_NEXT_SHIFTED_SPLIT :
336
				case Alignment2.M_ONE_PER_LINE_SPLIT :
337
					break;
338
				default:
339
					return;
340
			}
341
		}
342
		
343
		if (this.fragmentBreaks[this.fragmentIndex] == BREAK) {
344
			this.scribe.printNewLine();
345
		}
346
		if (this.fragmentIndentations[this.fragmentIndex] > 0) {
347
			this.scribe.indentationLevel = this.fragmentIndentations[this.fragmentIndex];
348
		}
349
	}					
350
351
	// reset fragment indentation/break status	
352
	public void reset() {
353
354
		if (fragmentCount > 0){
355
			this.fragmentIndentations = new int[this.fragmentCount];
356
			this.fragmentBreaks = new int[this.fragmentCount];
357
		}
358
359
		// check for forced alignments
360
		if ((mode & M_FORCE) != 0) {
361
			couldBreak();
362
		}		
363
	}		
364
365
	public void toFragmentsString(StringBuffer buffer){
366
		// default implementation
367
	}
368
	
369
	public String toString() {
370
		StringBuffer buffer = new StringBuffer(10);
371
		buffer
372
			.append(getClass().getName())
373
			.append(':')
374
			.append("<name: ")	//$NON-NLS-1$
375
			.append(this.name)
376
			.append(">");	//$NON-NLS-1$
377
		if (this.enclosing != null) {
378
			buffer
379
				.append("<enclosingName: ")	//$NON-NLS-1$
380
				.append(this.enclosing.name)
381
				.append('>');
382
		}
383
		buffer.append('\n');	
384
385
		for (int i = 0; i < this.fragmentCount; i++){
386
			buffer
387
				.append(" - fragment ")	//$NON-NLS-1$
388
				.append(i)
389
				.append(": ")	//$NON-NLS-1$
390
				.append("<break: ")	//$NON-NLS-1$
391
				.append(this.fragmentBreaks[i] > 0 ? "YES" : "NO")	//$NON-NLS-1$	//$NON-NLS-2$
392
				.append(">")	//$NON-NLS-1$
393
				.append("<indent: ")	//$NON-NLS-1$
394
				.append(this.fragmentIndentations[i])
395
				.append(">\n");	//$NON-NLS-1$
396
		}
397
		buffer.append('\n');	
398
		return buffer.toString();
399
	}
400
	
401
	public void update() {
402
		for (int i = 1; i < this.fragmentCount; i++){
403
		    if (this.fragmentBreaks[i] == BREAK) {
404
		        this.fragmentIndentations[i] = this.breakIndentationLevel;
405
		    }
406
		}
407
	}
408
409
	public boolean isWrapped() {
410
		for (int i = 0, max = this.fragmentCount; i < max; i++) {
411
			if (this.fragmentBreaks[i] == BREAK) {
412
				return true;
413
			}
414
		}
415
		return false;
416
	}
417
}

Return to bug 49412