1
/*******************************************************************************
2
* Copyright (c) 2000, 2009 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
9
* IBM Corporation - initial API and implementation
10
* Anton Leherbauer (Wind River Systems)
11
*******************************************************************************/
12
package org.eclipse.cdt.internal.formatter;
14
import java.util.Arrays;
15
import java.util.Collections;
16
import java.util.Iterator;
17
import java.util.List;
19
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants;
20
import org.eclipse.cdt.internal.formatter.align.Alignment;
21
import org.eclipse.cdt.internal.formatter.align.AlignmentException;
22
import org.eclipse.cdt.internal.formatter.scanner.Scanner;
23
import org.eclipse.cdt.internal.formatter.scanner.Token;
24
import org.eclipse.jface.text.Position;
25
import org.eclipse.text.edits.MultiTextEdit;
26
import org.eclipse.text.edits.ReplaceEdit;
27
import org.eclipse.text.edits.TextEdit;
30
* This class is responsible for dumping formatted source.
36
private static final String EMPTY_STRING= ""; //$NON-NLS-1$
37
private static final String SPACE= " "; //$NON-NLS-1$
39
private static final int INITIAL_SIZE= 100;
41
private final DefaultCodeFormatterOptions preferences;
42
public final Scanner scanner;
44
/** one-based column */
47
// Most specific alignment.
48
public Alignment currentAlignment;
49
public Alignment memberAlignment;
50
public AlignmentException currentAlignmentException;
52
public Token currentToken;
55
private OptimizedReplaceEdit[] edits;
56
public int editsIndex;
58
public int indentationLevel;
59
public int numberOfIndentations;
60
public int indentationSize;
62
private final String lineSeparator;
63
private final boolean indentEmptyLines;
64
private final int pageWidth;
65
private boolean preserveNewLines;
66
private boolean checkLineWrapping;
67
public int lastNumberOfNewLines;
70
public boolean needSpace= false;
71
public boolean pendingSpace= false;
75
private final boolean useTabsOnlyForLeadingIndents;
77
private int textRegionEnd;
78
private int textRegionStart;
79
public int scannerEndPosition;
81
private List<Position> fSkipPositions= Collections.emptyList();
83
private boolean skipOverInactive;
85
private int fSkipStartOffset= Integer.MAX_VALUE;
86
private int fSkipEndOffset;
87
private int fSkippedIndentations;
89
Scribe(CodeFormatterVisitor formatter, int offset, int length) {
90
scanner= new Scanner();
91
preferences= formatter.preferences;
92
pageWidth= preferences.page_width;
93
tabLength= preferences.tab_size;
94
indentationLevel= 0; // initialize properly
95
numberOfIndentations= 0;
96
useTabsOnlyForLeadingIndents= preferences.use_tabs_only_for_leading_indentations;
97
indentEmptyLines= preferences.indent_empty_lines;
98
tabChar= preferences.tab_char;
99
if (tabChar == DefaultCodeFormatterOptions.MIXED) {
100
indentationSize= preferences.indentation_size;
102
indentationSize= tabLength;
104
lineSeparator= preferences.line_separator;
105
indentationLevel= preferences.initial_indentation_level * indentationSize;
106
textRegionStart= offset;
107
textRegionEnd= offset + length - 1;
111
private final void addDeleteEdit(int start, int end) {
112
if (edits.length == editsIndex) {
116
addOptimizedReplaceEdit(start, end - start + 1, EMPTY_STRING);
119
public final void addInsertEdit(int insertPosition, String insertedString) {
120
if (edits.length == editsIndex) {
124
addOptimizedReplaceEdit(insertPosition, 0, insertedString);
127
private final void addOptimizedReplaceEdit(int offset, int length, String replacement) {
128
if (editsIndex > 0) {
129
// try to merge last two edits
130
final OptimizedReplaceEdit previous= edits[editsIndex - 1];
131
final int previousOffset= previous.offset;
132
final int previousLength= previous.length;
133
final int endOffsetOfPreviousEdit= previousOffset + previousLength;
134
final int replacementLength= replacement.length();
135
final String previousReplacement= previous.replacement;
136
final int previousReplacementLength= previousReplacement.length();
137
if (previousOffset == offset && previousLength == length
138
&& (replacementLength == 0 || previousReplacementLength == 0)) {
139
if (currentAlignment != null) {
140
final Location location= currentAlignment.location;
141
if (location.editsIndex == editsIndex) {
142
location.editsIndex--;
143
location.textEdit= previous;
149
if (endOffsetOfPreviousEdit == offset) {
151
if (replacementLength != 0) {
152
edits[editsIndex - 1]= new OptimizedReplaceEdit(previousOffset, previousLength + length,
153
previousReplacement + replacement);
154
} else if (previousLength + length == previousReplacementLength) {
155
// check the characters. If they are identical, we can
156
// get rid of the previous edit
157
boolean canBeRemoved= true;
158
loop: for (int i= previousOffset; i < previousOffset + previousReplacementLength; i++) {
159
if (scanner.source[i] != previousReplacement.charAt(i - previousOffset)) {
160
edits[editsIndex - 1]= new OptimizedReplaceEdit(previousOffset,
161
previousReplacementLength, previousReplacement);
167
if (currentAlignment != null) {
168
final Location location= currentAlignment.location;
169
if (location.editsIndex == editsIndex) {
170
location.editsIndex--;
171
location.textEdit= previous;
177
edits[editsIndex - 1]= new OptimizedReplaceEdit(previousOffset, previousLength + length,
178
previousReplacement);
181
if (replacementLength != 0) {
182
edits[editsIndex - 1]= new OptimizedReplaceEdit(previousOffset, previousLength,
183
previousReplacement + replacement);
187
assert endOffsetOfPreviousEdit < offset;
188
edits[editsIndex++]= new OptimizedReplaceEdit(offset, length, replacement);
191
edits[editsIndex++]= new OptimizedReplaceEdit(offset, length, replacement);
196
* Add a replace edit.
197
* @param start start offset (inclusive)
198
* @param end end offset (inclusive)
199
* @param replacement the replacement string
201
public final void addReplaceEdit(int start, int end, String replacement) {
202
if (edits.length == editsIndex) {
206
addOptimizedReplaceEdit(start, end - start + 1, replacement);
209
public void alignFragment(Alignment alignment, int fragmentIndex) {
210
alignment.fragmentIndex= fragmentIndex;
211
alignment.checkColumn();
212
alignment.performFragmentEffect();
215
public void consumeNextToken() {
217
currentToken= scanner.nextToken();
218
addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
221
public Alignment createAlignment(String name, int mode, int count, int sourceRestart) {
222
return createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart);
225
public Alignment createAlignment(String name, int mode, int count, int sourceRestart, boolean adjust) {
226
return createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart, adjust);
229
public Alignment createAlignment(String name, int mode, int tieBreakRule, int count, int sourceRestart) {
230
return createAlignment(name, mode, tieBreakRule, count, sourceRestart,
231
preferences.continuation_indentation, false);
234
public Alignment createAlignment(String name, int mode, int count, int sourceRestart, int continuationIndent,
236
return createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart, continuationIndent, adjust);
239
public Alignment createAlignment(String name, int mode, int tieBreakRule, int count, int sourceRestart,
240
int continuationIndent, boolean adjust) {
241
Alignment alignment= new Alignment(name, mode, tieBreakRule, this, count, sourceRestart, continuationIndent);
242
// adjust break indentation
243
if (adjust && memberAlignment != null) {
244
Alignment current= memberAlignment;
245
while (current.enclosing != null) {
246
current= current.enclosing;
248
if ((current.mode & Alignment.M_MULTICOLUMN) != 0) {
249
final int indentSize= indentationSize;
250
switch (current.chunkKind) {
251
case Alignment.CHUNK_METHOD:
252
case Alignment.CHUNK_TYPE:
253
if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
254
alignment.breakIndentationLevel= indentationLevel + indentSize;
256
alignment.breakIndentationLevel= indentationLevel + continuationIndent * indentSize;
260
case Alignment.CHUNK_FIELD:
261
if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
262
alignment.breakIndentationLevel= current.originalIndentationLevel + indentSize;
264
alignment.breakIndentationLevel= current.originalIndentationLevel + continuationIndent
271
switch (current.mode & Alignment.SPLIT_MASK) {
272
case Alignment.M_COMPACT_SPLIT:
273
case Alignment.M_COMPACT_FIRST_BREAK_SPLIT:
274
case Alignment.M_NEXT_PER_LINE_SPLIT:
275
case Alignment.M_NEXT_SHIFTED_SPLIT:
276
case Alignment.M_ONE_PER_LINE_SPLIT:
277
final int indentSize= indentationSize;
278
switch (current.chunkKind) {
279
case Alignment.CHUNK_METHOD:
280
case Alignment.CHUNK_TYPE:
281
if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
282
alignment.breakIndentationLevel= indentationLevel + indentSize;
284
alignment.breakIndentationLevel= indentationLevel + continuationIndent * indentSize;
288
case Alignment.CHUNK_FIELD:
289
if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
290
alignment.breakIndentationLevel= current.originalIndentationLevel + indentSize;
292
alignment.breakIndentationLevel= current.originalIndentationLevel + continuationIndent
305
public Alignment createMemberAlignment(String name, int mode, int count, int sourceRestart) {
306
Alignment mAlignment= createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart);
307
mAlignment.breakIndentationLevel= indentationLevel;
311
public void enterAlignment(Alignment alignment) {
312
alignment.enclosing= currentAlignment;
313
currentAlignment= alignment;
316
public void enterMemberAlignment(Alignment alignment) {
317
alignment.enclosing= memberAlignment;
318
memberAlignment= alignment;
321
public void exitAlignment(Alignment alignment, boolean discardAlignment) {
322
Alignment current= currentAlignment;
323
while (current != null) {
324
if (current == alignment)
326
current= current.enclosing;
328
if (current == null) {
329
throw new AbortFormatting("could not find matching alignment: " + alignment); //$NON-NLS-1$
331
indentationLevel= alignment.location.outputIndentationLevel;
332
numberOfIndentations= alignment.location.numberOfIndentations;
333
if (discardAlignment) {
334
currentAlignment= alignment.enclosing;
338
public void exitMemberAlignment(Alignment alignment) {
339
Alignment current= memberAlignment;
340
while (current != null) {
341
if (current == alignment)
343
current= current.enclosing;
345
if (current == null) {
346
throw new AbortFormatting("could not find matching alignment: " + alignment); //$NON-NLS-1$
348
indentationLevel= current.location.outputIndentationLevel;
349
numberOfIndentations= current.location.numberOfIndentations;
350
memberAlignment= current.enclosing;
353
public Alignment getAlignment(String name) {
354
if (currentAlignment != null) {
355
return currentAlignment.getAlignment(name);
361
* Answer actual indentation level based on true column position
365
public int getColumnIndentationLevel() {
369
public String getEmptyLines(int linesNumber) {
370
StringBuilder buffer= new StringBuilder();
371
if (lastNumberOfNewLines == 0) {
372
linesNumber++; // add an extra line breaks
373
for (int i= 0; i < linesNumber; i++) {
374
if (indentEmptyLines)
375
printIndentationIfNecessary(buffer);
376
buffer.append(lineSeparator);
378
lastNumberOfNewLines+= linesNumber;
383
} else if (lastNumberOfNewLines == 1) {
384
for (int i= 0; i < linesNumber; i++) {
385
if (indentEmptyLines)
386
printIndentationIfNecessary(buffer);
387
buffer.append(lineSeparator);
389
lastNumberOfNewLines+= linesNumber;
395
if ((lastNumberOfNewLines - 1) >= linesNumber) {
396
// there is no need to add new lines
399
final int realNewLineNumber= linesNumber - lastNumberOfNewLines + 1;
400
for (int i= 0; i < realNewLineNumber; i++) {
401
if (indentEmptyLines)
402
printIndentationIfNecessary(buffer);
403
buffer.append(lineSeparator);
405
lastNumberOfNewLines+= realNewLineNumber;
406
line+= realNewLineNumber;
411
return String.valueOf(buffer);
414
public OptimizedReplaceEdit getLastEdit() {
415
if (editsIndex > 0) {
416
return edits[editsIndex - 1];
421
Alignment getMemberAlignment() {
422
return memberAlignment;
425
public String getNewLine() {
426
if (lastNumberOfNewLines >= 1) {
427
column= 1; // ensure that the scribe is at the beginning of a new
432
lastNumberOfNewLines= 1;
436
return lineSeparator;
440
* Answer next indentation level based on column estimated position (if
441
* column is not indented, then use indentationLevel)
443
public int getNextIndentationLevel(int someColumn) {
444
int indent= someColumn - 1;
446
return indentationLevel;
447
if (tabChar == DefaultCodeFormatterOptions.TAB) {
448
if (useTabsOnlyForLeadingIndents) {
451
int rem= indent % indentationSize;
452
int addition= rem == 0 ? 0 : indentationSize - rem; // round to
454
return indent + addition;
460
private String getPreserveEmptyLines(int count) {
462
if (preferences.number_of_empty_lines_to_preserve != 0) {
463
int linesToPreserve= Math.min(count, preferences.number_of_empty_lines_to_preserve);
464
return getEmptyLines(linesToPreserve);
468
} else if (preserveNewLines) {
474
public TextEdit getRootEdit() {
475
MultiTextEdit edit= null;
476
int length= textRegionEnd - textRegionStart + 1;
477
if (textRegionStart <= 0) {
479
edit= new MultiTextEdit(0, 0);
481
edit= new MultiTextEdit(0, textRegionEnd + 1);
484
edit= new MultiTextEdit(textRegionStart, textRegionEnd - textRegionStart + 1);
486
for (int i= 0, max= editsIndex; i < max; i++) {
487
OptimizedReplaceEdit currentEdit= edits[i];
488
if (isValidEdit(currentEdit)) {
489
edit.addChild(new ReplaceEdit(currentEdit.offset, currentEdit.length, currentEdit.replacement));
496
public void handleLineTooLong() {
497
// search for closest breakable alignment, using tiebreak rules
498
// look for outermost breakable one
499
int relativeDepth= 0, outerMostDepth= -1;
500
Alignment targetAlignment= currentAlignment;
501
while (targetAlignment != null) {
502
if (targetAlignment.tieBreakRule == Alignment.R_OUTERMOST && targetAlignment.couldBreak()) {
503
outerMostDepth= relativeDepth;
505
targetAlignment= targetAlignment.enclosing;
508
if (outerMostDepth >= 0) {
509
throwAlignmentException(AlignmentException.LINE_TOO_LONG, outerMostDepth);
511
// look for innermost breakable one
513
targetAlignment= currentAlignment;
514
while (targetAlignment != null) {
515
if (targetAlignment.couldBreak()) {
516
throwAlignmentException(AlignmentException.LINE_TOO_LONG, relativeDepth);
518
targetAlignment= targetAlignment.enclosing;
521
// did not find any breakable location - proceed
524
private void throwAlignmentException(int kind, int relativeDepth) {
525
AlignmentException e= new AlignmentException(kind, relativeDepth);
526
currentAlignmentException= e;
530
public void indent() {
531
if (shouldSkip(scanner.getCurrentPosition())) {
532
fSkippedIndentations++;
535
indentationLevel+= indentationSize;
536
numberOfIndentations++;
540
* @param translationUnitSource
542
public void initializeScanner(char[] translationUnitSource) {
543
scanner.setSource(translationUnitSource);
544
scannerEndPosition= translationUnitSource.length;
545
scanner.resetTo(0, scannerEndPosition);
546
edits= new OptimizedReplaceEdit[INITIAL_SIZE];
552
public void setSkipPositions(List<Position> list) {
553
fSkipPositions= list;
554
skipOverInactive= !list.isEmpty();
557
private boolean isValidEdit(OptimizedReplaceEdit edit) {
558
final int editLength= edit.length;
559
final int editReplacementLength= edit.replacement.length();
560
final int editOffset= edit.offset;
561
if (editLength != 0) {
562
if (textRegionStart <= editOffset && (editOffset + editLength - 1) <= textRegionEnd) {
563
if (editReplacementLength != 0 && editLength == editReplacementLength) {
564
for (int i= editOffset, max= editOffset + editLength; i < max; i++) {
565
if (scanner.source[i] != edit.replacement.charAt(i - editOffset)) {
573
} else if (editOffset + editLength == textRegionStart) {
575
for (int max= editOffset + editLength; i < max; i++) {
576
int replacementStringIndex= i - editOffset;
577
if (replacementStringIndex >= editReplacementLength
578
|| scanner.source[i] != edit.replacement.charAt(replacementStringIndex)) {
582
if (i - editOffset != editReplacementLength && i != editOffset + editLength - 1) {
583
edit.offset= textRegionStart;
585
edit.replacement= edit.replacement.substring(i - editOffset);
589
} else if (textRegionStart <= editOffset && editOffset <= textRegionEnd) {
591
} else if (editOffset == scannerEndPosition && editOffset == textRegionEnd + 1) {
597
private void preserveEmptyLines(int count, int insertPosition) {
599
if (preferences.number_of_empty_lines_to_preserve != 0) {
600
int linesToPreserve= Math.min(count, preferences.number_of_empty_lines_to_preserve);
601
printEmptyLines(linesToPreserve, insertPosition);
603
printNewLine(insertPosition);
606
printNewLine(insertPosition);
610
public void printRaw(int startOffset, int length) {
614
int currentPosition= scanner.getCurrentPosition();
615
if (shouldSkip(currentPosition)) {
618
if (startOffset > currentPosition) {
620
currentPosition= scanner.getCurrentPosition();
623
addInsertEdit(currentPosition, SPACE);
627
if (startOffset + length < currentPosition) {
628
// don't move backwards
631
boolean savedPreserveNL= preserveNewLines;
632
boolean savedSkipOverInactive= skipOverInactive;
633
int savedScannerEndPos= scannerEndPosition;
634
preserveNewLines= true;
635
skipOverInactive= false;
636
scannerEndPosition= startOffset + length;
638
scanner.resetTo(Math.max(startOffset, currentPosition), startOffset + length - 1);
641
boolean hasWhitespace= printComment();
642
currentToken= scanner.nextToken();
643
if (currentToken == null) {
650
addInsertEdit(scanner.getCurrentTokenStartPosition(), SPACE);
654
switch (currentToken.type) {
655
case Token.tLBRACE: {
656
scanner.resetTo(scanner.getCurrentTokenStartPosition(), scannerEndPosition-1);
657
formatOpeningBrace(preferences.brace_position_for_block, preferences.insert_space_before_opening_brace_in_block);
658
if (preferences.indent_statements_compare_to_block) {
663
case Token.tRBRACE: {
664
scanner.resetTo(scanner.getCurrentTokenStartPosition(), scannerEndPosition-1);
665
if (preferences.indent_statements_compare_to_block) {
668
formatClosingBrace(preferences.brace_position_for_block);
673
print(currentToken.getLength(), hasWhitespace);
674
if (parenLevel > 0) {
675
for (int i= 0; i < preferences.continuation_indentation; i++) {
678
if (column <= indentationLevel) {
679
// HACK: avoid indent in same line
680
column= indentationLevel + 1;
686
if (parenLevel >= 0) {
687
for (int i= 0; i < preferences.continuation_indentation; i++) {
691
print(currentToken.getLength(), hasWhitespace);
694
print(currentToken.getLength(), preferences.insert_space_before_semicolon);
698
if (preferences.insert_new_line_before_else_in_if_statement) {
699
printNewLine(currentToken.offset);
703
print(currentToken.getLength(), hasWhitespace);
706
if (currentToken.isVisibilityModifier()
707
&& !preferences.indent_access_specifier_compare_to_type_header) {
708
int indentLevel= indentationLevel;
709
if (indentationLevel > 0)
711
print(currentToken.getLength(), hasWhitespace);
712
while (indentationLevel < indentLevel) {
716
print(currentToken.getLength(), hasWhitespace);
719
hasWhitespace= false;
722
scannerEndPosition= savedScannerEndPos;
723
scanner.resetTo(startOffset + length, scannerEndPosition - 1);
724
skipOverInactive= savedSkipOverInactive;
725
preserveNewLines= savedPreserveNL;
729
public void formatOpeningBrace(String bracePosition, boolean insertSpaceBeforeBrace) {
730
if (DefaultCodeFormatterConstants.NEXT_LINE.equals(bracePosition)) {
732
} else if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(bracePosition)) {
736
printNextToken(Token.tLBRACE, insertSpaceBeforeBrace);
738
printTrailingComment();
741
public void formatClosingBrace(String block_brace_position) {
742
printNextToken(Token.tRBRACE);
743
printTrailingComment();
744
if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(block_brace_position)) {
749
private void print(int length, boolean considerSpaceIfAny) {
750
if (checkLineWrapping && length + column > pageWidth) {
753
lastNumberOfNewLines= 0;
754
printIndentationIfNecessary();
755
if (considerSpaceIfAny) {
756
if (currentAlignment != null && currentAlignment.isIndentOnColumn(column)) {
762
addInsertEdit(scanner.getCurrentTokenStartPosition(), SPACE);
769
private void printBlockComment(boolean forceNewLine) {
770
int currentTokenStartPosition= scanner.getCurrentTokenStartPosition();
771
int currentTokenEndPosition= scanner.getCurrentTokenEndPosition() + 1;
773
scanner.resetTo(currentTokenStartPosition, currentTokenEndPosition - 1);
774
int currentCharacter;
775
boolean isNewLine= false;
776
int start= currentTokenStartPosition;
777
int nextCharacterStart= currentTokenStartPosition;
778
printIndentationIfNecessary();
780
addInsertEdit(currentTokenStartPosition, SPACE);
784
int previousStart= currentTokenStartPosition;
786
while (nextCharacterStart <= currentTokenEndPosition && (currentCharacter= scanner.getNextChar()) != -1) {
787
nextCharacterStart= scanner.getCurrentPosition();
789
switch (currentCharacter) {
794
start= previousStart;
796
if (scanner.getNextChar('\n')) {
797
currentCharacter= '\n';
798
nextCharacterStart= scanner.getCurrentPosition();
805
start= previousStart;
810
if (Character.isWhitespace((char) currentCharacter)) {
811
int previousStartPosition= scanner.getCurrentPosition();
812
while (currentCharacter != -1 && currentCharacter != '\r' && currentCharacter != '\n'
813
&& Character.isWhitespace((char) currentCharacter)) {
814
previousStart= nextCharacterStart;
815
previousStartPosition= scanner.getCurrentPosition();
816
currentCharacter= scanner.getNextChar();
817
nextCharacterStart= scanner.getCurrentPosition();
819
if (currentCharacter == '\r' || currentCharacter == '\n') {
820
nextCharacterStart= previousStartPosition;
826
StringBuilder buffer= new StringBuilder();
827
buffer.append(lineSeparator);
828
printIndentationIfNecessary(buffer);
831
addReplaceEdit(start, previousStart - 1, String.valueOf(buffer));
833
column+= (nextCharacterStart - previousStart);
837
previousStart= nextCharacterStart;
838
scanner.setCurrentPosition(nextCharacterStart);
840
lastNumberOfNewLines= 0;
842
scanner.resetTo(currentTokenEndPosition, scannerEndPosition - 1);
848
private void printPreprocessorDirective() {
849
int currentTokenStartPosition= scanner.getCurrentTokenStartPosition();
850
int currentTokenEndPosition= scanner.getCurrentTokenEndPosition() + 1;
852
scanner.resetTo(currentTokenStartPosition, currentTokenEndPosition - 1);
853
int currentCharacter;
854
boolean isNewLine= false;
855
int nextCharacterStart= currentTokenStartPosition;
858
int previousStart= currentTokenStartPosition;
860
while (nextCharacterStart <= currentTokenEndPosition && (currentCharacter= scanner.getNextChar()) != -1) {
861
nextCharacterStart= scanner.getCurrentPosition();
863
switch (currentCharacter) {
866
if (scanner.getNextChar('\n')) {
867
currentCharacter= '\n';
868
nextCharacterStart= scanner.getCurrentPosition();
879
column+= (nextCharacterStart - previousStart);
883
previousStart= nextCharacterStart;
884
scanner.setCurrentPosition(nextCharacterStart);
886
lastNumberOfNewLines= isNewLine ? 1 : 0;
888
if (currentAlignment != null) {
889
indentationLevel= currentAlignment.breakIndentationLevel;
891
scanner.resetTo(currentTokenEndPosition, scannerEndPosition - 1);
894
public void printEndOfTranslationUnit() {
895
int currentTokenStartPosition= scanner.getCurrentPosition();
896
if (currentTokenStartPosition <= scannerEndPosition) {
897
printRaw(currentTokenStartPosition, scannerEndPosition - currentTokenStartPosition + 1);
901
public boolean printComment() {
902
// if we have a space between two tokens we ensure it will be dumped in
903
// the formatted string
904
int currentTokenStartPosition= scanner.getCurrentPosition();
905
if (shouldSkip(currentTokenStartPosition)) {
908
boolean hasComment= false;
909
boolean hasLineComment= false;
910
boolean hasWhitespace= false;
912
while ((currentToken= scanner.nextToken()) != null) {
913
if (skipOverInactive) {
914
Position inactivePos= getInactivePosAt(scanner.getCurrentTokenStartPosition());
915
if (inactivePos != null) {
916
int startOffset= Math.min(scanner.getCurrentTokenStartPosition(), inactivePos.getOffset());
917
int endOffset= Math.min(scannerEndPosition, inactivePos.getOffset() + inactivePos.getLength());
918
if (startOffset < endOffset) {
919
int savedIndentLevel= indentationLevel;
920
scanner.resetTo(scanner.getCurrentTokenStartPosition(), scanner.eofPosition - 1);
921
printRaw(startOffset, endOffset - startOffset);
922
while (indentationLevel > savedIndentLevel) {
925
while (indentationLevel < savedIndentLevel) {
928
scanner.resetTo(endOffset, scanner.eofPosition - 1);
933
switch (currentToken.type) {
934
case Token.tWHITESPACE:
935
char[] whiteSpaces= scanner.getCurrentTokenSource();
937
for (int i= 0, max= whiteSpaces.length; i < max; i++) {
938
switch (whiteSpaces[i]) {
941
if (whiteSpaces[i + 1] == '\n') {
953
addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
954
} else if (hasComment) {
956
printNewLine(scanner.getCurrentTokenStartPosition());
958
preserveEmptyLines(count - 1, scanner.getCurrentTokenStartPosition());
960
addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
961
} else if (hasLineComment) {
962
preserveEmptyLines(count - 1, scanner.getCurrentTokenStartPosition());
963
addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
964
} else if (count != 0 && preferences.number_of_empty_lines_to_preserve != 0) {
965
String preservedEmptyLines= getPreserveEmptyLines(count - 1);
966
addReplaceEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
967
preservedEmptyLines);
968
hasWhitespace= preservedEmptyLines.length() == 0;
970
addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
973
currentTokenStartPosition= scanner.getCurrentPosition();
975
case Token.tLINECOMMENT:
978
preserveEmptyLines(count - 1, scanner.getCurrentTokenStartPosition());
979
} else if (count == 1) {
980
printNewLine(scanner.getCurrentTokenStartPosition());
982
} else if (hasWhitespace) {
985
hasWhitespace= false;
987
currentTokenStartPosition= scanner.getCurrentPosition();
988
hasLineComment= true;
991
case Token.tBLOCKCOMMENT:
994
preserveEmptyLines(count - 1, scanner.getCurrentTokenStartPosition());
995
} else if (count == 1) {
996
printNewLine(scanner.getCurrentTokenStartPosition());
998
} else if (hasWhitespace) {
1001
hasWhitespace= false;
1002
printBlockComment(false);
1003
currentTokenStartPosition= scanner.getCurrentPosition();
1004
hasLineComment= false;
1008
case Token.tPREPROCESSOR:
1009
case Token.tPREPROCESSOR_DEFINE:
1010
case Token.tPREPROCESSOR_INCLUDE:
1012
printNewLine(scanner.getCurrentTokenStartPosition());
1015
preserveEmptyLines(count - 1, scanner.getCurrentTokenStartPosition());
1016
} else if (count == 1) {
1017
// printNewLine(scanner.getCurrentTokenStartPosition());
1020
hasWhitespace= false;
1021
printPreprocessorDirective();
1023
currentTokenStartPosition= scanner.getCurrentPosition();
1024
hasLineComment= false;
1029
// step back one token
1030
scanner.resetTo(currentTokenStartPosition, scannerEndPosition - 1);
1031
return hasWhitespace;
1034
return hasWhitespace;
1041
private Position getInactivePosAt(int offset) {
1042
for (Iterator<Position> iter= fSkipPositions.iterator(); iter.hasNext();) {
1043
Position pos= iter.next();
1044
if (pos.includes(offset)) {
1051
private void printCommentLine() {
1052
int currentTokenStartPosition= scanner.getCurrentTokenStartPosition();
1053
int currentTokenEndPosition= scanner.getCurrentTokenEndPosition() + 1;
1054
scanner.resetTo(currentTokenStartPosition, currentTokenEndPosition - 1);
1055
int currentCharacter;
1056
int start= currentTokenStartPosition;
1057
int nextCharacterStart= currentTokenStartPosition;
1058
printIndentationIfNecessary();
1060
addInsertEdit(currentTokenStartPosition, SPACE);
1063
pendingSpace= false;
1064
int previousStart= currentTokenStartPosition;
1066
loop: while (nextCharacterStart <= currentTokenEndPosition && (currentCharacter= scanner.getNextChar()) != -1) {
1067
nextCharacterStart= scanner.getCurrentPosition();
1069
switch (currentCharacter) {
1071
start= previousStart;
1074
start= previousStart;
1077
previousStart= nextCharacterStart;
1079
if (start != currentTokenStartPosition) {
1080
addReplaceEdit(start, currentTokenEndPosition - 1, lineSeparator);
1085
pendingSpace= false;
1086
lastNumberOfNewLines= 0;
1087
scanner.resetTo(currentTokenEndPosition, scannerEndPosition - 1);
1088
// realign to the proper value
1089
if (currentAlignment != null) {
1090
if (memberAlignment != null) {
1091
// select the last alignment
1092
if (currentAlignment.location.inputOffset > memberAlignment.location.inputOffset) {
1093
if (currentAlignment.couldBreak() && currentAlignment.wasSplit) {
1094
currentAlignment.performFragmentEffect();
1097
indentationLevel= Math.max(indentationLevel, memberAlignment.breakIndentationLevel);
1099
} else if (currentAlignment.couldBreak() && currentAlignment.wasSplit) {
1100
currentAlignment.performFragmentEffect();
1105
public void printEmptyLines(int linesNumber) {
1106
printEmptyLines(linesNumber, scanner.getCurrentTokenEndPosition() + 1);
1109
private void printEmptyLines(int linesNumber, int insertPosition) {
1110
final String buffer= getEmptyLines(linesNumber);
1111
if (EMPTY_STRING == buffer)
1114
addInsertEdit(insertPosition, buffer);
1117
void printIndentationIfNecessary() {
1118
StringBuilder buffer= new StringBuilder();
1119
printIndentationIfNecessary(buffer);
1120
if (buffer.length() > 0) {
1121
addInsertEdit(scanner.getCurrentTokenStartPosition(), buffer.toString());
1122
pendingSpace= false;
1126
private void printIndentationIfNecessary(StringBuilder buffer) {
1128
case DefaultCodeFormatterOptions.TAB:
1129
boolean useTabsForLeadingIndents= useTabsOnlyForLeadingIndents;
1130
int numberOfLeadingIndents= numberOfIndentations;
1131
int indentationsAsTab= 0;
1132
if (useTabsForLeadingIndents) {
1133
while (column <= indentationLevel) {
1134
if (indentationsAsTab < numberOfLeadingIndents) {
1135
buffer.append('\t');
1136
indentationsAsTab++;
1137
lastNumberOfNewLines= 0;
1138
int complement= tabLength - ((column - 1) % tabLength); // amount
1141
column+= complement;
1150
while (column <= indentationLevel) {
1151
buffer.append('\t');
1152
lastNumberOfNewLines= 0;
1153
int complement= tabLength - ((column - 1) % tabLength); // amount
1156
column+= complement;
1161
case DefaultCodeFormatterOptions.SPACE:
1162
while (column <= indentationLevel) {
1168
case DefaultCodeFormatterOptions.MIXED:
1169
useTabsForLeadingIndents= useTabsOnlyForLeadingIndents;
1170
numberOfLeadingIndents= numberOfIndentations;
1171
indentationsAsTab= 0;
1172
if (useTabsForLeadingIndents) {
1173
final int columnForLeadingIndents= numberOfLeadingIndents * indentationSize;
1174
while (column <= indentationLevel) {
1175
if (column <= columnForLeadingIndents) {
1176
if ((column - 1 + tabLength) <= indentationLevel) {
1177
buffer.append('\t');
1179
} else if ((column - 1 + indentationSize) <= indentationLevel) {
1180
// print one indentation
1181
for (int i= 0, max= indentationSize; i < max; i++) {
1190
for (int i= column, max= indentationLevel; i <= max; i++) {
1198
while (column <= indentationLevel) {
1199
if ((column - 1 + tabLength) <= indentationLevel) {
1200
buffer.append('\t');
1202
} else if ((column - 1 + indentationSize) <= indentationLevel) {
1203
// print one indentation
1204
for (int i= 0, max= indentationSize; i < max; i++) {
1219
public void startNewLine() {
1224
public void printNewLine() {
1225
printNewLine(scanner.getCurrentTokenEndPosition() + 1);
1228
public void printNewLine(int insertPosition) {
1229
if (shouldSkip(insertPosition - 1)) {
1232
if (lastNumberOfNewLines >= 1) {
1233
column= 1; // ensure that the scribe is at the beginning of a new line
1236
addInsertEdit(insertPosition, lineSeparator);
1238
lastNumberOfNewLines= 1;
1241
pendingSpace= false;
1244
public void printNextToken(int expectedTokenType) {
1245
printNextToken(expectedTokenType, false);
1248
public void printNextToken(int expectedTokenType, boolean considerSpaceIfAny) {
1250
if (shouldSkip(scanner.getCurrentPosition())) {
1253
currentToken= scanner.nextToken();
1254
if (currentToken == null || expectedTokenType != currentToken.type) {
1256
addInsertEdit(scanner.getCurrentTokenStartPosition(), SPACE);
1258
pendingSpace= false;
1260
throw new AbortFormatting(
1261
"[" + (line+1) + "/" + column + "] unexpected token type, expecting:" + expectedTokenType + ", actual:" + currentToken);//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
1263
print(currentToken.getLength(), considerSpaceIfAny);
1266
public void printNextToken(int[] expectedTokenTypes) {
1267
printNextToken(expectedTokenTypes, false);
1270
public void printNextToken(int[] expectedTokenTypes, boolean considerSpaceIfAny) {
1272
if (shouldSkip(scanner.getCurrentPosition())) {
1275
currentToken= scanner.nextToken();
1276
if (Arrays.binarySearch(expectedTokenTypes, currentToken.type) < 0) {
1278
addInsertEdit(scanner.getCurrentTokenStartPosition(), SPACE);
1280
pendingSpace= false;
1282
StringBuilder expectations= new StringBuilder(5);
1283
for (int i= 0; i < expectedTokenTypes.length; i++) {
1285
expectations.append(',');
1287
expectations.append(expectedTokenTypes[i]);
1289
throw new AbortFormatting(
1290
"[" + (line+1) + "/" + column + "] unexpected token type, expecting:[" + expectations.toString() + "], actual:" + currentToken);//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
1292
print(currentToken.getLength(), considerSpaceIfAny);
1295
private void printRule(StringBuilder stringBuffer) {
1296
for (int i= 0; i < pageWidth; i++) {
1297
if ((i % tabLength) == 0) {
1298
stringBuffer.append('+');
1300
stringBuffer.append('-');
1303
stringBuffer.append(lineSeparator);
1305
for (int i= 0; i < (pageWidth / tabLength); i++) {
1306
stringBuffer.append(i);
1307
stringBuffer.append('\t');
1311
public void printTrailingComment() {
1312
// if we have a space between two tokens we ensure it will be dumped in
1313
// the formatted string
1314
int currentTokenStartPosition= scanner.getCurrentPosition();
1315
if (shouldSkip(currentTokenStartPosition)) {
1318
boolean hasWhitespaces= false;
1319
boolean hasComment= false;
1320
boolean hasLineComment= false;
1322
while ((currentToken= scanner.nextToken()) != null) {
1323
switch (currentToken.type) {
1324
case Token.tWHITESPACE:
1325
char[] whiteSpaces= scanner.getCurrentTokenSource();
1326
for (int i= 0, max= whiteSpaces.length; i < max; i++) {
1327
switch (whiteSpaces[i]) {
1329
if ((i + 1) < max) {
1330
if (whiteSpaces[i + 1] == '\n') {
1340
if (hasLineComment) {
1342
currentTokenStartPosition= scanner.getCurrentTokenStartPosition();
1343
preserveEmptyLines(count - 1, currentTokenStartPosition);
1344
addDeleteEdit(currentTokenStartPosition, scanner.getCurrentTokenEndPosition());
1345
scanner.resetTo(scanner.getCurrentPosition(), scannerEndPosition - 1);
1348
scanner.resetTo(currentTokenStartPosition, scannerEndPosition - 1);
1351
} else if (count >= 1) {
1353
printNewLine(scanner.getCurrentTokenStartPosition());
1355
scanner.resetTo(currentTokenStartPosition, scannerEndPosition - 1);
1358
hasWhitespaces= true;
1359
currentTokenStartPosition= scanner.getCurrentPosition();
1360
addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1363
case Token.tLINECOMMENT:
1364
if (hasWhitespaces) {
1368
currentTokenStartPosition= scanner.getCurrentPosition();
1369
hasLineComment= true;
1371
case Token.tBLOCKCOMMENT:
1372
if (hasWhitespaces) {
1375
printBlockComment(false);
1376
currentTokenStartPosition= scanner.getCurrentPosition();
1379
case Token.tPREPROCESSOR:
1380
case Token.tPREPROCESSOR_DEFINE:
1381
case Token.tPREPROCESSOR_INCLUDE:
1383
printNewLine(scanner.getCurrentTokenStartPosition());
1384
hasWhitespaces= false;
1385
printPreprocessorDirective();
1387
currentTokenStartPosition= scanner.getCurrentPosition();
1388
hasLineComment= false;
1393
// step back one token
1394
scanner.resetTo(currentTokenStartPosition, scannerEndPosition - 1);
1400
void redoAlignment(AlignmentException e) {
1401
if (e.relativeDepth > 0) { // if exception targets a distinct context
1402
e.relativeDepth--; // record fact that current context got
1404
currentAlignment= currentAlignment.enclosing; // pop currentLocation
1407
// reset scribe/scanner to restart at this given location
1408
resetAt(currentAlignment.location);
1409
scanner.resetTo(currentAlignment.location.inputOffset, scanner.eofPosition - 1);
1410
// clean alignment chunkKind so it will think it is a new chunk again
1411
currentAlignment.chunkKind= 0;
1412
currentAlignmentException= null;
1415
void redoMemberAlignment(AlignmentException e) {
1416
// reset scribe/scanner to restart at this given location
1417
resetAt(memberAlignment.location);
1418
scanner.resetTo(memberAlignment.location.inputOffset, scanner.eofPosition - 1);
1419
// clean alignment chunkKind so it will think it is a new chunk again
1420
memberAlignment.chunkKind= 0;
1421
currentAlignmentException= null;
1424
public void reset() {
1425
checkLineWrapping= true;
1431
private void resetAt(Location location) {
1432
line= location.outputLine;
1433
column= location.outputColumn;
1434
indentationLevel= location.outputIndentationLevel;
1435
numberOfIndentations= location.numberOfIndentations;
1436
lastNumberOfNewLines= location.lastNumberOfNewLines;
1437
needSpace= location.needSpace;
1438
pendingSpace= location.pendingSpace;
1439
editsIndex= location.editsIndex;
1440
if (editsIndex > 0) {
1441
edits[editsIndex - 1]= location.textEdit;
1445
private void resize() {
1446
System.arraycopy(edits, 0, (edits= new OptimizedReplaceEdit[editsIndex * 2]), 0, editsIndex);
1449
public void space() {
1452
if (shouldSkip(scanner.getCurrentPosition())) {
1455
lastNumberOfNewLines= 0;
1462
public String toString() {
1463
StringBuilder buffer= new StringBuilder();
1464
buffer.append("(page width = " + pageWidth + ") - (tabChar = ");//$NON-NLS-1$//$NON-NLS-2$
1466
case DefaultCodeFormatterOptions.TAB:
1467
buffer.append("TAB");//$NON-NLS-1$
1469
case DefaultCodeFormatterOptions.SPACE:
1470
buffer.append("SPACE");//$NON-NLS-1$
1473
buffer.append("MIXED");//$NON-NLS-1$
1476
.append(") - (tabSize = " + tabLength + ")")//$NON-NLS-1$//$NON-NLS-2$
1477
.append(lineSeparator)
1479
"(line = " + line + ") - (column = " + column + ") - (identationLevel = " + indentationLevel + ")") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
1480
.append(lineSeparator)
1482
"(needSpace = " + needSpace + ") - (lastNumberOfNewLines = " + lastNumberOfNewLines + ") - (checkLineWrapping = " + checkLineWrapping + ")") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
1483
.append(lineSeparator).append(
1484
"==================================================================================") //$NON-NLS-1$
1485
.append(lineSeparator);
1487
return buffer.toString();
1490
public void unIndent() {
1491
if (shouldSkip(scanner.getCurrentPosition())) {
1492
fSkippedIndentations--;
1495
indentationLevel-= indentationSize;
1496
numberOfIndentations--;
1501
public boolean printModifiers() {
1502
int currentTokenStartPosition= scanner.getCurrentPosition();
1503
if (shouldSkip(currentTokenStartPosition)) {
1506
boolean isFirstModifier= true;
1507
boolean hasComment= false;
1508
while ((currentToken= scanner.nextToken()) != null) {
1509
switch (currentToken.type) {
1510
case Token.t_typedef:
1511
case Token.t_extern:
1512
case Token.t_static:
1514
case Token.t_register:
1516
case Token.t_signed:
1517
case Token.t_unsigned:
1518
case Token.t_volatile:
1519
case Token.t_virtual:
1520
case Token.t_mutable:
1521
case Token.t_explicit:
1522
case Token.t_friend:
1523
case Token.t_inline:
1524
case Token.t_restrict:
1525
print(currentToken.getLength(), !isFirstModifier);
1526
isFirstModifier= false;
1527
currentTokenStartPosition= scanner.getCurrentPosition();
1529
case Token.tBLOCKCOMMENT:
1530
printBlockComment(false);
1531
currentTokenStartPosition= scanner.getCurrentPosition();
1534
case Token.tLINECOMMENT:
1536
currentTokenStartPosition= scanner.getCurrentPosition();
1538
case Token.tWHITESPACE:
1539
addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
1541
char[] whiteSpaces= scanner.getCurrentTokenSource();
1542
for (int i= 0, max= whiteSpaces.length; i < max; i++) {
1543
switch (whiteSpaces[i]) {
1545
if ((i + 1) < max) {
1546
if (whiteSpaces[i + 1] == '\n') {
1556
if (count >= 1 && hasComment) {
1559
currentTokenStartPosition= scanner.getCurrentPosition();
1562
case Token.tPREPROCESSOR:
1563
case Token.tPREPROCESSOR_DEFINE:
1564
case Token.tPREPROCESSOR_INCLUDE:
1566
printNewLine(scanner.getCurrentTokenStartPosition());
1567
printPreprocessorDirective();
1569
currentTokenStartPosition= scanner.getCurrentPosition();
1573
if (currentToken.getType() == Token.tIDENTIFIER) {
1574
if (currentToken.getText().startsWith("__")) { //$NON-NLS-1$
1575
// assume this is a declspec modifier
1576
print(currentToken.getLength(), !isFirstModifier);
1577
isFirstModifier= false;
1578
currentTokenStartPosition= scanner.getCurrentPosition();
1579
if ((currentToken= scanner.nextToken()) != null) {
1580
if (currentToken.getType() == Token.tLPAREN) {
1581
if (skipToToken(Token.tRPAREN)) {
1582
currentToken= scanner.nextToken();
1583
currentToken= scanner.nextToken();
1584
currentTokenStartPosition= scanner.getCurrentPosition();
1591
// step back one token
1592
scanner.resetTo(currentTokenStartPosition, scannerEndPosition - 1);
1593
return !isFirstModifier;
1596
return !isFirstModifier;
1599
public boolean preserveNewLine() {
1600
boolean savedPreserveNewLines= preserveNewLines;
1602
preserveNewLines= true;
1603
return printComment();
1605
preserveNewLines= savedPreserveNewLines;
1610
* Skip to the next occurrence of the given token type.
1611
* If successful, the next token will be the epxected token,
1612
* otherwise the scanner position is left unchanged.
1614
* @param expectedTokenType
1615
* @return <code>true</code> if a matching token was skipped to
1617
public boolean skipToToken(int expectedTokenType) {
1618
int skipStart= scanner.getCurrentPosition();
1619
if (shouldSkip(skipStart)) {
1624
switch (expectedTokenType) {
1632
while ((currentToken= scanner.nextToken()) != null) {
1633
switch (currentToken.type) {
1635
if (expectedTokenType != Token.tLBRACE) {
1643
if (expectedTokenType != Token.tLPAREN) {
1650
case Token.tWHITESPACE:
1651
case Token.tLINECOMMENT:
1652
case Token.tBLOCKCOMMENT:
1653
case Token.tPREPROCESSOR:
1654
case Token.tPREPROCESSOR_DEFINE:
1655
case Token.tPREPROCESSOR_INCLUDE:
1658
if (braceLevel <= 0 && parenLevel <= 0) {
1659
if (currentToken.type == expectedTokenType) {
1660
int tokenStart= scanner.getCurrentTokenStartPosition();
1661
printRaw(skipStart, tokenStart - skipStart);
1662
scanner.resetTo(tokenStart, scannerEndPosition - 1);
1666
if (braceLevel < 0 || parenLevel < 0) {
1670
scanner.resetTo(skipStart, scannerEndPosition - 1);
1674
public boolean printCommentPreservingNewLines() {
1675
final boolean savedPreserveNL= this.preserveNewLines;
1676
this.preserveNewLines= true;
1678
return printComment();
1680
this.preserveNewLines= savedPreserveNL;
1684
boolean shouldSkip(int offset) {
1685
return offset >= fSkipStartOffset;
1688
void skipRange(int offset, int endOffset) {
1689
if (offset == fSkipStartOffset) {
1692
final int currentPosition= scanner.getCurrentPosition();
1693
if (offset > currentPosition) {
1694
printRaw(currentPosition, currentPosition - offset);
1696
fSkipStartOffset= offset;
1697
fSkipEndOffset= endOffset;
1700
boolean skipRange() {
1701
return fSkipEndOffset > 0;
1704
void restartAtOffset(int offset) {
1705
final int currentPosition= scanner.getCurrentPosition();
1706
if (fSkipEndOffset > 0) {
1707
fSkipStartOffset= Integer.MAX_VALUE;
1709
while (fSkippedIndentations < 0) {
1711
fSkippedIndentations++;
1713
if (offset > currentPosition) {
1714
printRaw(currentPosition, offset - currentPosition);
1715
scanner.resetTo(offset, scannerEndPosition - 1);
1717
while (fSkippedIndentations > 0) {
1719
fSkippedIndentations--;
1721
} else if (offset > currentPosition) {
1722
boolean hasSpace= printComment();
1723
final int nextPosition= scanner.getCurrentPosition();
1724
if (offset > nextPosition) {
1728
printRaw(nextPosition, offset - nextPosition);
1729
scanner.resetTo(offset, scannerEndPosition - 1);