2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* Portions Copyrighted 2007 Sun Microsystems, Inc.
28
package org.netbeans.modules.java.source.save;
30
import com.sun.source.tree.*;
31
import com.sun.source.util.SourcePositions;
32
import com.sun.source.util.TreePath;
33
import com.sun.source.util.TreePathScanner;
34
import com.sun.tools.javac.api.JavacTaskImpl;
35
import com.sun.tools.javac.api.JavacTrees;
36
import com.sun.tools.javac.code.Flags;
37
import com.sun.tools.javac.main.JavaCompiler;
38
import com.sun.tools.javac.tree.JCTree;
39
import com.sun.tools.javac.tree.JCTree.JCBlock;
40
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
41
import com.sun.tools.javac.tree.JCTree.JCModifiers;
43
import java.io.IOException;
46
import javax.lang.model.element.Name;
47
import javax.swing.text.BadLocationException;
48
import javax.swing.text.Document;
50
import org.netbeans.api.java.classpath.ClassPath;
51
import org.netbeans.api.java.lexer.JavaTokenId;
52
import org.netbeans.modules.java.source.parsing.FileObjects;
53
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
54
import static org.netbeans.api.java.lexer.JavaTokenId.*;
55
import org.netbeans.api.java.source.*;
56
import org.netbeans.api.lexer.Token;
57
import org.netbeans.api.lexer.TokenHierarchy;
58
import org.netbeans.api.lexer.TokenSequence;
59
import org.netbeans.modules.java.source.JavaSourceAccessor;
60
import org.netbeans.modules.editor.indent.spi.Context;
61
import org.netbeans.modules.editor.indent.spi.ExtraLock;
62
import org.netbeans.modules.editor.indent.spi.ReformatTask;
68
public class Reformatter implements ReformatTask {
70
private JavaSource javaSource;
71
private Context context;
72
private CompilationController controller;
76
public Reformatter(JavaSource javaSource, Context context) {
77
this.javaSource = javaSource;
78
this.context = context;
79
this.doc = context.document();
82
public void reformat() throws BadLocationException {
83
if (controller == null) {
85
javaSource.runUserActionTask(new Task<CompilationController>() {
86
public void run(CompilationController controller) throws Exception {
87
controller.toPhase(JavaSource.Phase.PARSED);
88
Reformatter.this.controller = controller;
91
} catch (IOException ioe) {
92
JavaSourceAccessor.INSTANCE.unlockJavaCompiler();
94
if (controller == null)
97
for (Context.Region region : context.indentRegions())
101
public static String reformat(String text, CodeStyle style) {
102
StringBuilder sb = new StringBuilder(text);
104
ClassPath empty = ClassPathSupport.createClassPath(new URL[0]);
105
ClasspathInfo cpInfo = ClasspathInfo.create(empty, empty, empty);
106
JavacTaskImpl javacTask = JavaSourceAccessor.INSTANCE.createJavacTask(cpInfo, null, null);
107
com.sun.tools.javac.util.Context ctx = javacTask.getContext();
108
JavaCompiler.instance(ctx).genEndPos = true;
109
CompilationUnitTree tree = javacTask.parse(FileObjects.memoryFileObject(text, "")).iterator().next(); //NOI18N
110
SourcePositions sp = JavacTrees.instance(ctx).getSourcePositions();
111
TokenSequence<JavaTokenId> tokens = TokenHierarchy.create(text, JavaTokenId.language()).tokenSequence(JavaTokenId.language());
112
for (Diff diff : Pretty.reformat(text, new TreePath(tree), sp, tokens, style)) {
113
int start = diff.getStartOffset();
114
int end = diff.getEndOffset();
115
sb.delete(start, end);
116
String t = diff.getText();
117
if (t != null && t.length() > 0) {
122
} catch (IOException ioe) {
124
return sb.toString();
127
private void reformatImpl(Context.Region region) throws BadLocationException {
128
int startOffset = region.getStartOffset() - shift;
129
int endOffset = region.getEndOffset() - shift;
130
int originalEndOffset = endOffset;
131
PositionConverter converter = controller.getPositionConverter();
132
if (converter != null) {
133
startOffset = converter.getJavaSourcePosition(startOffset);
134
assert startOffset >= 0 : "Converted startOffset is wrong: " + startOffset;
135
endOffset = converter.getJavaSourcePosition(endOffset);
136
assert endOffset >= 0 : "Converted endOffset is wrong: " + endOffset;
138
int embeddingOffset = -1;
139
if (!"text/x-java".equals(context.mimePath())) { //NOI18N
140
TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language());
142
ts.move(startOffset);
144
if (ts.token().id() == WHITESPACE) {
145
String t = ts.token().text().toString();
146
if (ts.offset() < startOffset)
147
t = t.substring(startOffset - ts.offset());
148
if (t.indexOf('\n') < 0) //NOI18N
149
embeddingOffset = ts.offset() + ts.token().length();
151
embeddingOffset = startOffset;
155
if (ts.moveNext() && ts.token().id() == WHITESPACE) {
156
String t = ts.token().text().toString();
157
if (ts.offset() + t.length() > endOffset)
158
t = t.substring(0, endOffset - ts.offset());
159
int i = t.lastIndexOf('\n'); //NOI18N
161
endOffset -= (t.length() - i);
165
if (startOffset >= endOffset)
167
TreePath path = getCommonPath(startOffset, endOffset);
170
for (Diff diff : Pretty.reformat(controller, path, CodeStyle.getDefault(null))) {
171
int start = diff.getStartOffset();
172
int end = diff.getEndOffset();
173
String text = diff.getText();
174
if (startOffset > end || endOffset < start || embeddingOffset >= start)
176
if (startOffset > start) {
177
if (text != null && text.length() > 0)
178
text = startOffset - start >= text.length() ? null : text.substring(startOffset - start);
181
if (endOffset < end) {
182
if (text != null && text.length() > 0)
183
text = end - endOffset >= text.length() ? null : text.substring(0, text.length() - end + endOffset);
186
if (converter != null) {
187
start = converter.getOriginalPosition(start);
188
end = converter.getOriginalPosition(end);
192
doc.remove(start, end - start);
193
if (text != null && text.length() > 0)
194
doc.insertString(start, text, null);
196
shift = region.getEndOffset() - originalEndOffset;
200
public ExtraLock reformatLock() {
204
private TreePath getCommonPath(int startOffset, int endOffset) {
205
TreeUtilities tu = controller.getTreeUtilities();
206
TreePath startPath = tu.pathFor(startOffset);
207
com.sun.tools.javac.util.List<Tree> reverseStartPath = com.sun.tools.javac.util.List.<Tree>nil();
208
for (Tree t : startPath)
209
reverseStartPath = reverseStartPath.prepend(t);
210
TreePath endPath = tu.pathFor(endOffset);
211
com.sun.tools.javac.util.List<Tree> reverseEndPath = com.sun.tools.javac.util.List.<Tree>nil();
212
for (Tree t : endPath)
213
reverseEndPath = reverseEndPath.prepend(t);
214
TreePath path = null;
215
while(reverseStartPath.head != null && reverseStartPath.head == reverseEndPath.head) {
216
path = reverseStartPath.head instanceof CompilationUnitTree ? new TreePath((CompilationUnitTree)reverseStartPath.head) : new TreePath(path, reverseStartPath.head);
217
reverseStartPath = reverseStartPath.tail;
218
reverseEndPath = reverseEndPath.tail;
223
private class Lock implements ExtraLock {
226
JavaSourceAccessor.INSTANCE.lockJavaCompiler();
229
public void unlock() {
231
JavaSourceAccessor.INSTANCE.unlockJavaCompiler();
235
public static class Factory implements ReformatTask.Factory {
237
public ReformatTask createTask(Context context) {
238
JavaSource js = JavaSource.forDocument(context.document());
239
return js != null ? new Reformatter(js, context) : null;
243
private static class Pretty extends TreePathScanner<Boolean, Void> {
245
private static final String OPERATOR = "operator"; //NOI18N
246
private static final String EMPTY = ""; //NOI18N
247
private static final String SPACE = " "; //NOI18N
248
private static final String NEWLINE = "\n"; //NOI18N
249
private static final String ERROR = "<error>"; //NOI18N
250
private static final int ANY_COUNT = -1;
252
private final String fText;
253
private final SourcePositions sp;
254
private final CodeStyle cs;
256
private final int rightMargin;
257
private final int tabSize;
258
private final int indentSize;
259
private final int continuationIndentSize;
260
private final boolean expandTabToSpaces;
262
private TokenSequence<JavaTokenId> tokens;
266
private int wrapDepth;
267
private int lastBlankLines;
268
private int lastBlankLinesTokenIndex;
269
private Diff lastBlankLinesDiff;
270
private boolean afterAnnotation;
271
private boolean fieldGroup;
272
private boolean afterNewline;
273
private LinkedList<Diff> diffs = new LinkedList<Diff>();
275
private Pretty(CompilationInfo info, TreePath path, CodeStyle cs) {
276
this(info, info.getText(), info.getTrees().getSourcePositions(),
277
path.getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT
278
? info.getTokenHierarchy().tokenSequence(JavaTokenId.language())
279
: info.getTreeUtilities().tokensFor(path.getLeaf()),
283
private Pretty(CompilationInfo info, String text, SourcePositions sp, TokenSequence<JavaTokenId> tokens, TreePath path, CodeStyle cs) {
287
this.rightMargin = cs.getRightMargin();
288
this.tabSize = cs.getTabSize();
289
this.indentSize = cs.getIndentSize();
290
this.continuationIndentSize = cs.getContinuationIndentSize();
291
this.expandTabToSpaces = cs.expandTabToSpaces();
293
this.lastBlankLines = -1;
294
this.lastBlankLinesTokenIndex = -1;
295
this.lastBlankLinesDiff = null;
296
this.afterAnnotation = false;
297
this.fieldGroup = false;
298
Tree tree = path.getLeaf();
299
this.indent = info != null ? getIndentLevel(info, path) : 0;
300
this.col = this.indent;
301
this.tokens = tokens;
303
tokens.movePrevious();
304
this.endPos = tokens.offset();
309
public static LinkedList<Diff> reformat(CompilationInfo info, TreePath path, CodeStyle cs) {
310
Pretty pretty = new Pretty(info, path, cs);
311
if (pretty.indent >= 0)
312
pretty.scan(path, null);
313
if (path.getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) {
314
pretty.tokens.moveEnd();
315
pretty.tokens.movePrevious();
316
if (pretty.tokens.token().id() != WHITESPACE || pretty.tokens.token().text().toString().indexOf('\n') < 0) {
317
String text = info.getText();
318
pretty.diffs.addFirst(new Diff(text.length(), text.length(), NEWLINE));
324
public static LinkedList<Diff> reformat(String text, TreePath path, SourcePositions sp, TokenSequence<JavaTokenId> tokens, CodeStyle cs) {
325
Pretty pretty = new Pretty(null, text, sp, tokens, path, cs);
326
pretty.scan(path, null);
328
tokens.movePrevious();
329
if (tokens.token().id() != WHITESPACE || tokens.token().text().toString().indexOf('\n') < 0)
330
pretty.diffs.addFirst(new Diff(text.length(), text.length(), NEWLINE));
335
public Boolean scan(Tree tree, Void p) {
336
int lastEndPos = endPos;
337
if (tree != null && tree.getKind() != Tree.Kind.COMPILATION_UNIT) {
338
if (tree instanceof FakeBlock)
339
endPos = (int)sp.getEndPosition(getCurrentPath().getCompilationUnit(), ((FakeBlock)tree).stat);
341
endPos = (int)sp.getEndPosition(getCurrentPath().getCompilationUnit(), tree);
344
return endPos < 0 ? false : tokens.offset() <= endPos ? super.scan(tree, p) : true;
352
public Boolean visitCompilationUnit(CompilationUnitTree node, Void p) {
353
ExpressionTree pkg = node.getPackageName();
355
blankLines(cs.getBlankLinesBeforePackage());
358
indent += continuationIndentSize;
363
blankLines(cs.getBlankLinesAfterPackage());
365
List<? extends ImportTree> imports = node.getImports();
366
if (imports != null && !imports.isEmpty()) {
367
blankLines(cs.getBlankLinesBeforeImports());
368
for (ImportTree imp : imports) {
372
blankLines(cs.getBlankLinesAfterImports());
374
for (Tree typeDecl : node.getTypeDecls()) {
375
blankLines(cs.getBlankLinesBeforeClass());
377
blankLines(cs.getBlankLinesAfterClass());
383
public Boolean visitImport(ImportTree node, Void p) {
386
indent += continuationIndentSize;
388
if (node.isStatic()) {
392
scan(node.getQualifiedIdentifier(), p);
399
public Boolean visitClass(ClassTree node, Void p) {
400
Tree parent = getCurrentPath().getParentPath().getLeaf();
401
if (parent.getKind() != Tree.Kind.NEW_CLASS && (parent.getKind() != Tree.Kind.VARIABLE || !isEnumerator((VariableTree)parent))) {
403
ModifiersTree mods = node.getModifiers();
406
indent += continuationIndentSize;
408
} else if (afterAnnotation) {
412
JavaTokenId id = accept(CLASS, INTERFACE, ENUM, AT);
414
indent += continuationIndentSize;
418
if (!ERROR.contentEquals(node.getSimpleName()))
420
List<? extends TypeParameterTree> tparams = node.getTypeParameters();
421
if (tparams != null && !tparams.isEmpty()) {
423
for (Iterator<? extends TypeParameterTree> it = tparams.iterator(); it.hasNext();) {
424
TypeParameterTree tparam = it.next();
427
spaces(cs.spaceBeforeComma() ? 1 : 0);
429
spaces(cs.spaceAfterComma() ? 1 : 0);
432
accept(GT, GTGT, GTGTGT);
434
Tree ext = node.getExtendsClause();
436
wrapToken(cs.wrapExtendsImplementsKeyword(), 1, EXTENDS);
440
List<? extends Tree> impls = node.getImplementsClause();
441
if (impls != null && !impls.isEmpty()) {
442
wrapToken(cs.wrapExtendsImplementsKeyword(), 1, id == INTERFACE ? EXTENDS : IMPLEMENTS);
444
wrapList(cs.wrapExtendsImplementsList(), cs.alignMultilineImplements(), impls);
448
CodeStyle.BracePlacement bracePlacement = cs.getClassDeclBracePlacement();
449
boolean spaceBeforeLeftBrace = cs.spaceBeforeClassDeclLeftBrace();
451
int halfIndent = indent;
452
switch(bracePlacement) {
454
spaces(spaceBeforeLeftBrace ? 1 : 0);
456
indent += indentSize;
461
indent += indentSize;
463
case NEW_LINE_HALF_INDENTED:
464
indent += (indentSize >> 1);
468
indent = old + indentSize;
470
case NEW_LINE_INDENTED:
471
indent += indentSize;
477
boolean emptyClass = true;
478
for (Tree member : node.getMembers()) {
479
if (!isSynthetic(getCurrentPath().getCompilationUnit(), member)) {
487
if (!cs.indentTopLevelClassMembers())
489
blankLines(cs.getBlankLinesAfterClassHeader());
490
JavaTokenId id = null;
491
boolean first = true;
492
for (Tree member : node.getMembers()) {
493
if (!isSynthetic(getCurrentPath().getCompilationUnit(), member)) {
494
switch(member.getKind()) {
496
if (isEnumerator((VariableTree)member)) {
497
wrapTree(cs.wrapEnumConstants(), id == COMMA ? 1 : 0, member);
498
int index = tokens.index();
500
Diff d = diffs.isEmpty() ? null : diffs.getFirst();
501
id = accept(COMMA, SEMICOLON);
503
rollback(index, c, d);
504
blankLines(cs.getBlankLinesAfterFields());
505
} else if (id == SEMICOLON) {
506
blankLines(cs.getBlankLinesAfterFields());
509
if (!fieldGroup && !first)
510
blankLines(cs.getBlankLinesBeforeFields());
513
blankLines(cs.getBlankLinesAfterFields());
519
blankLines(cs.getBlankLinesBeforeMethods());
521
blankLines(cs.getBlankLinesAfterMethods());
525
blankLines(cs.getBlankLinesBeforeClass());
527
blankLines(cs.getBlankLinesAfterClass());
535
Diff diff = diffs.isEmpty() ? null : diffs.getFirst();
536
if (diff != null && diff.end == tokens.offset()) {
537
if (diff.text != null) {
538
int idx = diff.text.lastIndexOf('\n'); //NOI18N
540
diff.text = getIndent();
542
diff.text = diff.text.substring(0, idx + 1) + getIndent();
545
String spaces = diff.text != null ? diff.text : getIndent();
546
if (spaces.equals(fText.substring(diff.start, diff.end)))
555
public Boolean visitVariable(VariableTree node, Void p) {
557
Tree parent = getCurrentPath().getParentPath().getLeaf();
558
boolean insideFor = parent.getKind() == Tree.Kind.FOR_LOOP;
559
ModifiersTree mods = node.getModifiers();
563
indent += continuationIndentSize;
565
} else if (afterAnnotation) {
566
if (parent.getKind() == Tree.Kind.CLASS || parent.getKind() == Tree.Kind.BLOCK) {
573
if (isEnumerator(node)) {
575
ExpressionTree init = node.getInitializer();
576
if (init != null && init.getKind() == Tree.Kind.NEW_CLASS) {
577
NewClassTree nct = (NewClassTree)init;
578
int index = tokens.index();
580
Diff d = diffs.isEmpty() ? null :diffs.getFirst();
581
spaces(cs.spaceBeforeMethodCallParen() ? 1 : 0);
582
JavaTokenId id = accept(LPAREN);
584
rollback(index, c, d);
585
List<? extends ExpressionTree> args = nct.getArguments();
586
if (args != null && !args.isEmpty()) {
587
spaces(cs.spaceWithinMethodCallParens() ? 1 : 0, true);
588
wrapList(cs.wrapMethodCallArgs(), cs.alignMultilineCallArgs(), args);
589
spaces(cs.spaceWithinMethodCallParens() ? 1 : 0);
593
ClassTree body = nct.getClassBody();
598
if (indent == old && !insideFor)
599
indent += continuationIndentSize;
600
if (scan(node.getType(), p)) {
601
spaces(1, fieldGroup);
602
if (!ERROR.contentEquals(node.getName()))
605
ExpressionTree init = node.getInitializer();
607
spaces(cs.spaceAroundAssignOps() ? 1 : 0);
609
wrapTree(cs.wrapAssignOps(), cs.spaceAroundAssignOps() ? 1 : 0, init);
611
fieldGroup = accept(SEMICOLON, COMMA) == COMMA;
618
public Boolean visitMethod(MethodTree node, Void p) {
620
ModifiersTree mods = node.getModifiers();
623
indent += continuationIndentSize;
629
List<? extends TypeParameterTree> tparams = node.getTypeParameters();
630
if (tparams != null && !tparams.isEmpty()) {
633
indent += continuationIndentSize;
634
for (Iterator<? extends TypeParameterTree> it = tparams.iterator(); it.hasNext();) {
635
TypeParameterTree tparam = it.next();
638
spaces(cs.spaceBeforeComma() ? 1 : 0);
640
spaces(cs.spaceAfterComma() ? 1 : 0);
643
accept(GT, GTGT, GTGTGT);
646
Tree retType = node.getReturnType();
647
if (retType != null) {
650
indent += continuationIndentSize;
653
if (!ERROR.contentEquals(node.getName()))
656
indent += continuationIndentSize;
657
spaces(cs.spaceBeforeMethodDeclParen() ? 1 : 0);
659
List<? extends VariableTree> params = node.getParameters();
660
if (params != null && !params.isEmpty()) {
661
spaces(cs.spaceWithinMethodDeclParens() ? 1 : 0, true);
662
wrapList(cs.wrapMethodParams(), cs.alignMultilineMethodParams(), params);
663
spaces(cs.spaceWithinMethodDeclParens() ? 1 : 0);
666
List<? extends ExpressionTree> threxs = node.getThrows();
667
if (threxs != null && !threxs.isEmpty()) {
668
wrapToken(cs.wrapThrowsKeyword(), 1, THROWS);
670
wrapList(cs.wrapThrowsList(), cs.alignMultilineThrows(), threxs);
672
Tree init = node.getDefaultValue();
674
spaces(cs.spaceAroundAssignOps() ? 1 : 0);
676
spaces(cs.spaceAroundAssignOps() ? 1 : 0);
680
BlockTree body = node.getBody();
690
public Boolean visitModifiers(ModifiersTree node, Void p) {
692
JavaTokenId id = null;
693
afterAnnotation = false;
694
Iterator<? extends AnnotationTree> annotations = node.getAnnotations().iterator();
695
TreePath path = getCurrentPath().getParentPath();
696
Tree parent = path.getLeaf();
697
path = path.getParentPath();
698
Tree grandParent = path.getLeaf();
699
boolean isForVariable = parent.getKind() == Tree.Kind.VARIABLE &&
700
(grandParent.getKind() == Tree.Kind.FOR_LOOP || grandParent.getKind() == Tree.Kind.ENHANCED_FOR_LOOP);
701
while (tokens.offset() < endPos) {
702
if (afterAnnotation) {
706
switch (cs.wrapAnnotations()) {
711
if (col >= rightMargin)
720
} else if (id != null) {
723
int index = tokens.index();
725
Diff d = diffs.isEmpty() ? null : diffs.getFirst();
726
int lbl = lastBlankLines;
727
int lblti = lastBlankLinesTokenIndex;
728
Diff lbld = lastBlankLinesDiff;
729
id = accept(PRIVATE, PROTECTED, PUBLIC, STATIC, TRANSIENT, FINAL,
730
ABSTRACT, NATIVE, VOLATILE, SYNCHRONIZED, STRICTFP, AT);
734
if (annotations.hasNext()) {
735
rollback(index, c, d);
736
lastBlankLines = lbl;
737
lastBlankLinesTokenIndex = lblti;
738
lastBlankLinesDiff = lbld;
740
scan(annotations.next(), p);
742
wrapTree(cs.wrapAnnotations(), 0, annotations.next());
744
afterAnnotation = true;
748
afterAnnotation = false;
751
afterAnnotation = false;
753
col += tokens.token().length();
760
public Boolean visitAnnotation(AnnotationTree node, Void p) {
762
scan(node.getAnnotationType(), p);
763
List<? extends ExpressionTree> args = node.getArguments();
764
spaces(cs.spaceBeforeAnnotationParen() ? 1 : 0);
766
if (args != null && !args.isEmpty()) {
767
spaces(cs.spaceWithinAnnotationParens() ? 1 : 0);
768
for (Iterator<? extends ExpressionTree> it = args.iterator(); it.hasNext();) {
769
ExpressionTree arg = it.next();
772
spaces(cs.spaceBeforeComma() ? 1 : 0);
774
spaces(cs.spaceAfterComma() ? 1 : 0);
777
spaces(cs.spaceWithinAnnotationParens() ? 1 : 0);
784
public Boolean visitTypeParameter(TypeParameterTree node, Void p) {
785
if (!ERROR.contentEquals(node.getName()))
787
List<? extends Tree> bounds = node.getBounds();
788
if (bounds != null && !bounds.isEmpty()) {
792
for (Iterator<? extends Tree> it = bounds.iterator(); it.hasNext();) {
793
Tree bound = it.next();
806
public Boolean visitParameterizedType(ParameterizedTypeTree node, Void p) {
807
scan(node.getType(), p);
808
List<? extends Tree> targs = node.getTypeArguments();
809
if (targs != null && !targs.isEmpty()) {
811
for (Iterator<? extends Tree> it = targs.iterator(); it.hasNext();) {
812
Tree targ = it.next();
815
spaces(cs.spaceBeforeComma() ? 1 : 0);
817
spaces(cs.spaceAfterComma() ? 1 : 0);
820
accept(GT, GTGT, GTGTGT);
826
public Boolean visitWildcard(WildcardTree node, Void p) {
828
Tree bound = node.getBound();
831
accept(EXTENDS, SUPER);
839
public Boolean visitBlock(BlockTree node, Void p) {
842
CodeStyle.BracePlacement bracePlacement;
843
boolean spaceBeforeLeftBrace = false;
844
switch (getCurrentPath().getParentPath().getLeaf().getKind()) {
846
bracePlacement = cs.getOtherBracePlacement();
848
spaceBeforeLeftBrace = cs.spaceBeforeStaticInitLeftBrace();
851
bracePlacement = cs.getMethodDeclBracePlacement();
852
spaceBeforeLeftBrace = cs.spaceBeforeMethodDeclLeftBrace();
855
bracePlacement = cs.getOtherBracePlacement();
856
if (((TryTree)getCurrentPath().getParentPath().getLeaf()).getBlock() == node)
857
spaceBeforeLeftBrace = cs.spaceBeforeTryLeftBrace();
859
spaceBeforeLeftBrace = cs.spaceBeforeFinallyLeftBrace();
862
bracePlacement = cs.getOtherBracePlacement();
863
spaceBeforeLeftBrace = cs.spaceBeforeCatchLeftBrace();
866
bracePlacement = cs.getOtherBracePlacement();
867
spaceBeforeLeftBrace = cs.spaceBeforeWhileLeftBrace();
870
case ENHANCED_FOR_LOOP:
871
bracePlacement = cs.getOtherBracePlacement();
872
spaceBeforeLeftBrace = cs.spaceBeforeForLeftBrace();
875
bracePlacement = cs.getOtherBracePlacement();
876
spaceBeforeLeftBrace = cs.spaceBeforeDoLeftBrace();
879
bracePlacement = cs.getOtherBracePlacement();
880
if (((IfTree)getCurrentPath().getParentPath().getLeaf()).getThenStatement() == node)
881
spaceBeforeLeftBrace = cs.spaceBeforeIfLeftBrace();
883
spaceBeforeLeftBrace = cs.spaceBeforeElseLeftBrace();
886
bracePlacement = cs.getOtherBracePlacement();
887
spaceBeforeLeftBrace = cs.spaceBeforeSynchronizedLeftBrace();
890
bracePlacement = cs.getOtherBracePlacement();
891
spaceBeforeLeftBrace = true;
894
bracePlacement = cs.getOtherBracePlacement();
898
int halfIndent = indent;
899
switch(bracePlacement) {
901
spaces(spaceBeforeLeftBrace ? 1 : 0);
902
if (node instanceof FakeBlock) {
903
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), "{")); //NOI18N
907
indent += indentSize;
911
if (node instanceof FakeBlock) {
912
indent += indentSize;
913
String s = "{" + getNewlines(1) + getIndent();
914
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), s)); //NOI18N
917
indent += indentSize;
920
case NEW_LINE_HALF_INDENTED:
921
indent += (indentSize >> 1);
924
if (node instanceof FakeBlock) {
925
indent = old + indentSize;
926
String s = "{" + getNewlines(1) + getIndent();
927
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), s)); //NOI18N
930
indent = old + indentSize;
933
case NEW_LINE_INDENTED:
934
indent += indentSize;
937
if (node instanceof FakeBlock) {
938
String s = "{" + getNewlines(1) + getIndent();
939
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), s)); //NOI18N
945
for (StatementTree stat : node.getStatements()) {
946
if (!isSynthetic(getCurrentPath().getCompilationUnit(), stat)) {
947
if (stat.getKind() == Tree.Kind.LABELED_STATEMENT && cs.absoluteLabelIndent()) {
953
if (!fieldGroup || stat.getKind() != Tree.Kind.VARIABLE)
959
if (node instanceof FakeBlock) {
960
String s = getNewlines(1) + getIndent() + "}"; //NOI18N
962
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), s));
965
Diff diff = diffs.isEmpty() ? null : diffs.getFirst();
966
if (diff != null && diff.end == tokens.offset()) {
967
if (diff.text != null) {
968
int idx = diff.text.lastIndexOf('\n'); //NOI18N
970
diff.text = getIndent();
972
diff.text = diff.text.substring(0, idx + 1) + getIndent();
975
String spaces = diff.text != null ? diff.text : getIndent();
976
if (spaces.equals(fText.substring(diff.start, diff.end)))
986
public Boolean visitMemberSelect(MemberSelectTree node, Void p) {
987
scan(node.getExpression(), p);
989
accept(IDENTIFIER, STAR, THIS, SUPER, CLASS);
994
public Boolean visitMethodInvocation(MethodInvocationTree node, Void p) {
995
ExpressionTree ms = node.getMethodSelect();
996
if (ms.getKind() == Tree.Kind.MEMBER_SELECT) {
997
ExpressionTree exp = ((MemberSelectTree)ms).getExpression();
1000
List<? extends Tree> targs = node.getTypeArguments();
1001
if (targs != null && !targs.isEmpty()) {
1003
for (Iterator<? extends Tree> it = targs.iterator(); it.hasNext();) {
1004
Tree targ = it.next();
1007
spaces(cs.spaceBeforeComma() ? 1 : 0);
1009
spaces(cs.spaceAfterComma() ? 1 : 0);
1012
accept(GT, GTGT, GTGTGT);
1014
if(exp.getKind() == Tree.Kind.METHOD_INVOCATION)
1015
wrapToken(cs.wrapChainedMethodCalls(), 0, IDENTIFIER);
1019
scan(node.getMethodSelect(), p);
1021
spaces(cs.spaceBeforeMethodCallParen() ? 1 : 0);
1023
List<? extends ExpressionTree> args = node.getArguments();
1024
if (args != null && !args.isEmpty()) {
1025
spaces(cs.spaceWithinMethodCallParens() ? 1 : 0, true);
1026
wrapList(cs.wrapMethodCallArgs(), cs.alignMultilineCallArgs(), args);
1027
spaces(cs.spaceWithinMethodCallParens() ? 1 : 0);
1034
public Boolean visitNewClass(NewClassTree node, Void p) {
1035
ExpressionTree encl = node.getEnclosingExpression();
1040
boolean indented = false;
1041
if (col == indent) {
1042
Diff d = diffs.isEmpty() ? null : diffs.getFirst();
1043
if (d != null && d.getStartOffset() == tokens.offset() && d.getText() != null && d.getText().indexOf('\n') >= 0) {
1046
tokens.movePrevious();
1047
if (tokens.token().id() == WHITESPACE && tokens.token().text().toString().indexOf('\n') >= 0)
1054
List<? extends Tree> targs = node.getTypeArguments();
1055
if (targs != null && !targs.isEmpty()) {
1057
for (Iterator<? extends Tree> it = targs.iterator(); it.hasNext();) {
1058
Tree targ = it.next();
1061
spaces(cs.spaceBeforeComma() ? 1 : 0);
1063
spaces(cs.spaceAfterComma() ? 1 : 0);
1066
accept(GT, GTGT, GTGTGT);
1068
scan(node.getIdentifier(), p);
1069
spaces(cs.spaceBeforeMethodCallParen() ? 1 : 0);
1071
List<? extends ExpressionTree> args = node.getArguments();
1072
if (args != null && !args.isEmpty()) {
1073
spaces(cs.spaceWithinMethodCallParens() ? 1 : 0, true);
1074
wrapList(cs.wrapMethodCallArgs(), cs.alignMultilineCallArgs(), args);
1075
spaces(cs.spaceWithinMethodCallParens() ? 1 : 0);
1078
ClassTree body = node.getClassBody();
1082
indent -= continuationIndentSize;
1090
public Boolean visitAssert(AssertTree node, Void p) {
1093
indent += continuationIndentSize;
1095
scan(node.getCondition(), p);
1096
ExpressionTree detail = node.getDetail();
1097
if (detail != null) {
1098
spaces(cs.spaceBeforeColon() ? 1 : 0);
1100
wrapTree(cs.wrapAssert(), cs.spaceAfterColon() ? 1 : 0, detail);
1108
public Boolean visitReturn(ReturnTree node, Void p) {
1111
indent += continuationIndentSize;
1112
ExpressionTree exp = node.getExpression();
1123
public Boolean visitThrow(ThrowTree node, Void p) {
1126
indent += continuationIndentSize;
1127
ExpressionTree exp = node.getExpression();
1138
public Boolean visitTry(TryTree node, Void p) {
1140
scan(node.getBlock(), p);
1141
for (CatchTree catchTree : node.getCatches()) {
1142
if (cs.placeCatchOnNewLine())
1145
spaces(cs.spaceBeforeCatch() ? 1 : 0);
1148
BlockTree finallyBlockTree = node.getFinallyBlock();
1149
if (finallyBlockTree != null) {
1150
if (cs.placeFinallyOnNewLine())
1153
spaces(cs.spaceBeforeFinally() ? 1 : 0);
1155
scan(finallyBlockTree, p);
1161
public Boolean visitCatch(CatchTree node, Void p) {
1164
indent += continuationIndentSize;
1165
spaces(cs.spaceBeforeCatchParen() ? 1 : 0);
1167
spaces(cs.spaceWithinCatchParens() ? 1 : 0);
1168
scan(node.getParameter(), p);
1169
spaces(cs.spaceWithinCatchParens() ? 1 : 0);
1172
scan(node.getBlock(), p);
1177
public Boolean visitIf(IfTree node, Void p) {
1180
indent += continuationIndentSize;
1181
spaces(cs.spaceBeforeIfParen() ? 1 : 0);
1182
scan(node.getCondition(), p);
1184
boolean prevblock = wrapStatement(cs.wrapIfStatement(), cs.redundantIfBraces(), cs.spaceBeforeIfLeftBrace() ? 1 : 0, node.getThenStatement());
1185
StatementTree elseStat = node.getElseStatement();
1186
if (elseStat != null) {
1187
if (cs.placeElseOnNewLine() || !prevblock) {
1190
spaces(cs.spaceBeforeElse() ? 1 : 0);
1193
if (elseStat.getKind() == Tree.Kind.IF && cs.specialElseIf()) {
1197
wrapStatement(cs.wrapIfStatement(), cs.redundantIfBraces(), cs.spaceBeforeElseLeftBrace() ? 1 : 0, elseStat);
1205
public Boolean visitDoWhileLoop(DoWhileLoopTree node, Void p) {
1208
boolean prevblock = wrapStatement(cs.wrapDoWhileStatement(), cs.redundantDoWhileBraces(), cs.spaceBeforeDoLeftBrace() ? 1 : 0, node.getStatement());
1209
if (cs.placeWhileOnNewLine() || !prevblock) {
1212
spaces(cs.spaceBeforeWhile() ? 1 : 0);
1215
indent += continuationIndentSize;
1216
spaces(cs.spaceBeforeWhileParen() ? 1 : 0);
1217
scan(node.getCondition(), p);
1224
public Boolean visitWhileLoop(WhileLoopTree node, Void p) {
1227
indent += continuationIndentSize;
1228
spaces(cs.spaceBeforeWhileParen() ? 1 : 0);
1229
scan(node.getCondition(), p);
1231
wrapStatement(cs.wrapWhileStatement(), cs.redundantWhileBraces(), cs.spaceBeforeWhileLeftBrace() ? 1 : 0, node.getStatement());
1236
public Boolean visitForLoop(ForLoopTree node, Void p) {
1239
indent += continuationIndentSize;
1240
spaces(cs.spaceBeforeForParen() ? 1 : 0);
1242
List<? extends StatementTree> inits = node.getInitializer();
1243
if (inits != null && !inits.isEmpty()) {
1244
spaces(cs.spaceWithinForParens() ? 1 : 0);
1245
for (Iterator<? extends StatementTree> it = inits.iterator(); it.hasNext();) {
1246
StatementTree init = it.next();
1249
spaces(cs.spaceBeforeComma() ? 1 : 0);
1251
spaces(cs.spaceAfterComma() ? 1 : 0);
1254
spaces(cs.spaceBeforeSemi() ? 1 : 0);
1257
ExpressionTree cond = node.getCondition();
1259
wrapTree(cs.wrapFor(), cs.spaceAfterSemi() ? 1 : 0, cond);
1260
spaces(cs.spaceBeforeSemi() ? 1 : 0);
1263
List<? extends ExpressionStatementTree> updates = node.getUpdate();
1264
if (updates != null && !updates.isEmpty()) {
1265
boolean first = true;
1266
for (Iterator<? extends ExpressionStatementTree> it = updates.iterator(); it.hasNext();) {
1267
ExpressionStatementTree update = it.next();
1269
wrapTree(cs.wrapFor(), cs.spaceAfterSemi() ? 1 : 0, update);
1275
spaces(cs.spaceBeforeComma() ? 1 : 0);
1277
spaces(cs.spaceAfterComma() ? 1 : 0);
1280
spaces(cs.spaceWithinForParens() ? 1 : 0);
1284
wrapStatement(cs.wrapForStatement(), cs.redundantForBraces(), cs.spaceBeforeForLeftBrace() ? 1 : 0, node.getStatement());
1289
public Boolean visitEnhancedForLoop(EnhancedForLoopTree node, Void p) {
1292
indent += continuationIndentSize;
1293
spaces(cs.spaceBeforeForParen() ? 1 : 0);
1295
spaces(cs.spaceWithinForParens() ? 1 : 0);
1296
scan(node.getVariable(), p);
1297
spaces(cs.spaceBeforeColon() ? 1 : 0);
1299
spaces(cs.spaceAfterColon() ? 1 : 0);
1300
scan(node.getExpression(), p);
1301
spaces(cs.spaceWithinForParens() ? 1 : 0);
1304
wrapStatement(cs.wrapForStatement(), cs.redundantForBraces(), cs.spaceBeforeForLeftBrace() ? 1 : 0, node.getStatement());
1309
public Boolean visitSynchronized(SynchronizedTree node, Void p) {
1310
accept(SYNCHRONIZED);
1312
indent += continuationIndentSize;
1313
spaces(cs.spaceBeforeSynchronizedParen() ? 1 : 0);
1314
scan(node.getExpression(), p);
1316
scan(node.getBlock(), p);
1321
public Boolean visitSwitch(SwitchTree node, Void p) {
1324
indent += continuationIndentSize;
1325
spaces(cs.spaceBeforeSwitchParen() ? 1 : 0);
1326
scan(node.getExpression(), p);
1327
CodeStyle.BracePlacement bracePlacement = cs.getOtherBracePlacement();
1328
boolean spaceBeforeLeftBrace = cs.spaceBeforeSwitchLeftBrace();
1329
boolean indentCases = cs.indentCasesFromSwitch();
1331
int halfIndent = indent;
1332
switch(bracePlacement) {
1334
spaces(spaceBeforeLeftBrace ? 1 : 0);
1337
indent += indentSize;
1343
indent += indentSize;
1345
case NEW_LINE_HALF_INDENTED:
1346
indent += (indentSize >> 1);
1347
halfIndent = indent;
1351
indent = old + indentSize;
1355
case NEW_LINE_INDENTED:
1356
indent += indentSize;
1357
halfIndent = indent;
1364
for (CaseTree caseTree : node.getCases()) {
1369
indent = halfIndent;
1370
Diff diff = diffs.isEmpty() ? null : diffs.getFirst();
1371
if (diff != null && diff.end == tokens.offset()) {
1372
if (diff.text != null) {
1373
int idx = diff.text.lastIndexOf('\n'); //NOI18N
1375
diff.text = getIndent();
1377
diff.text = diff.text.substring(0, idx + 1) + getIndent();
1380
String spaces = diff.text != null ? diff.text : getIndent();
1381
if (spaces.equals(fText.substring(diff.start, diff.end)))
1382
diffs.removeFirst();
1390
public Boolean visitCase(CaseTree node, Void p) {
1391
ExpressionTree exp = node.getExpression();
1401
indent += indentSize;
1402
for (Iterator<? extends StatementTree> it = node.getStatements().iterator(); it.hasNext();) {
1403
StatementTree stat = it.next();
1404
if (stat.getKind() == Tree.Kind.BLOCK && !it.hasNext()) {
1417
public Boolean visitBreak(BreakTree node, Void p) {
1419
Name label = node.getLabel();
1420
if (label != null) {
1429
public Boolean visitContinue(ContinueTree node, Void p) {
1431
Name label = node.getLabel();
1432
if (label != null) {
1441
public Boolean visitAssignment(AssignmentTree node, Void p) {
1442
boolean b = scan(node.getVariable(), p);
1443
if (b || getCurrentPath().getParentPath().getLeaf().getKind() != Tree.Kind.ANNOTATION) {
1444
spaces(cs.spaceAroundAssignOps() ? 1 : 0);
1446
wrapTree(cs.wrapAssignOps(), cs.spaceAroundAssignOps() ? 1 : 0, node.getExpression());
1448
scan(node.getExpression(), p);
1455
public Boolean visitCompoundAssignment(CompoundAssignmentTree node, Void p) {
1456
scan(node.getVariable(), p);
1457
spaces(cs.spaceAroundAssignOps() ? 1 : 0);
1458
if (OPERATOR.equals(tokens.token().id().primaryCategory())) {
1459
col += tokens.token().length();
1460
lastBlankLines = -1;
1461
lastBlankLinesTokenIndex = -1;
1462
lastBlankLinesDiff = null;
1465
wrapTree(cs.wrapAssignOps(), cs.spaceAroundAssignOps() ? 1 : 0, node.getExpression());
1471
public Boolean visitPrimitiveType(PrimitiveTypeTree node, Void p) {
1472
switch (node.getPrimitiveTypeKind()) {
1505
public Boolean visitArrayType(ArrayTypeTree node, Void p) {
1506
boolean ret = scan(node.getType(), p);
1507
int index = tokens.index();
1509
Diff d = diffs.isEmpty() ? null : diffs.getFirst();
1510
JavaTokenId id = accept(LBRACKET, ELLIPSIS, IDENTIFIER);
1513
if (id != IDENTIFIER) {
1517
rollback(index, c, d);
1518
spaces(1, fieldGroup);
1526
public Boolean visitArrayAccess(ArrayAccessTree node, Void p) {
1527
scan(node.getExpression(), p);
1529
scan(node.getIndex(), p);
1535
public Boolean visitNewArray(NewArrayTree node, Void p) {
1536
Tree type = node.getType();
1537
List<? extends ExpressionTree> inits = node.getInitializers();
1541
int n = inits != null ? 1 : 0;
1542
while (type.getKind() == Tree.Kind.ARRAY_TYPE) {
1544
type = ((ArrayTypeTree)type).getType();
1547
for (ExpressionTree dim : node.getDimensions()) {
1549
spaces(cs.spaceWithinArrayInitBrackets() ? 1 : 0);
1551
spaces(cs.spaceWithinArrayInitBrackets() ? 1 : 0);
1559
if (inits != null) {
1561
indent += (indentSize - continuationIndentSize);
1563
spaces(cs.spaceBeforeArrayInitLeftBrace() ? 1 : 0);
1565
if (!inits.isEmpty()) {
1566
afterNewline = false;
1567
spaces(cs.spaceWithinBraces() ? 1 : 0, true);
1568
wrapList(cs.wrapArrayInit(), cs.alignMultilineArrayInit(), inits);
1569
indent -= indentSize;
1573
spaces(cs.spaceWithinBraces() ? 1 : 0);
1582
public Boolean visitIdentifier(IdentifierTree node, Void p) {
1583
accept(IDENTIFIER, THIS, SUPER);
1588
public Boolean visitUnary(UnaryTree node, Void p) {
1589
if (OPERATOR.equals(tokens.token().id().primaryCategory())) {
1590
spaces(cs.spaceAroundUnaryOps() ? 1 : 0);
1591
col += tokens.token().length();
1592
lastBlankLines = -1;
1593
lastBlankLinesTokenIndex = -1;
1594
lastBlankLinesDiff = null;
1596
spaces(cs.spaceAroundUnaryOps() ? 1 : 0);
1597
scan(node.getExpression(), p);
1599
scan(node.getExpression(), p);
1600
spaces(cs.spaceAroundUnaryOps() ? 1 : 0);
1601
col += tokens.token().length();
1602
lastBlankLines = -1;
1603
lastBlankLinesTokenIndex = -1;
1604
lastBlankLinesDiff = null;
1606
spaces(cs.spaceAroundUnaryOps() ? 1 : 0);
1612
public Boolean visitBinary(BinaryTree node, Void p) {
1613
scan(node.getLeftOperand(), p);
1614
spaces(cs.spaceAroundBinaryOps() ? 1 : 0);
1615
if (OPERATOR.equals(tokens.token().id().primaryCategory())) {
1616
col += tokens.token().length();
1617
lastBlankLines = -1;
1618
lastBlankLinesTokenIndex = -1;
1621
wrapTree(cs.wrapBinaryOps(), cs.spaceAroundBinaryOps() ? 1 : 0, node.getRightOperand());
1626
public Boolean visitConditionalExpression(ConditionalExpressionTree node, Void p) {
1627
scan(node.getCondition(), p);
1628
wrapToken(cs.wrapTernaryOps(), cs.spaceAroundTernaryOps() ? 1 : 0, QUESTION);
1629
spaces(cs.spaceAroundTernaryOps() ? 1 : 0);
1630
scan(node.getTrueExpression(), p);
1631
wrapToken(cs.wrapTernaryOps(), cs.spaceAroundTernaryOps() ? 1 : 0, COLON);
1632
spaces(cs.spaceAroundTernaryOps() ? 1 : 0);
1633
scan(node.getFalseExpression(), p);
1638
public Boolean visitEmptyStatement(EmptyStatementTree node, Void p) {
1644
public Boolean visitExpressionStatement(ExpressionStatementTree node, Void p) {
1646
indent += continuationIndentSize;
1647
scan(node.getExpression(), p);
1654
public Boolean visitInstanceOf(InstanceOfTree node, Void p) {
1655
scan(node.getExpression(), p);
1659
scan(node.getType(), p);
1664
public Boolean visitLabeledStatement(LabeledStatementTree node, Void p) {
1665
if (!ERROR.contentEquals(node.getLabel()))
1669
indent += cs.getLabelIndent();
1670
int cnt = indent - col;
1675
scan(node.getStatement(), p);
1681
public Boolean visitTypeCast(TypeCastTree node, Void p) {
1683
boolean spaceWithinParens = cs.spaceWithinTypeCastParens();
1684
spaces(spaceWithinParens ? 1 : 0);
1685
scan(node.getType(), p);
1686
spaces(spaceWithinParens ? 1 : 0);
1688
spaces(cs.spaceAfterTypeCast() ? 1 : 0);
1689
scan(node.getExpression(), p);
1694
public Boolean visitParenthesized(ParenthesizedTree node, Void p) {
1696
boolean spaceWithinParens;
1697
switch(getCurrentPath().getParentPath().getLeaf().getKind()) {
1699
spaceWithinParens = cs.spaceWithinIfParens();
1702
spaceWithinParens = cs.spaceWithinForParens();
1706
spaceWithinParens = cs.spaceWithinWhileParens();
1709
spaceWithinParens = cs.spaceWithinSwitchParens();
1712
spaceWithinParens = cs.spaceWithinSynchronizedParens();
1715
spaceWithinParens = cs.spaceWithinParens();
1717
spaces(spaceWithinParens ? 1 : 0);
1718
scan(node.getExpression(), p);
1719
spaces(spaceWithinParens ? 1 : 0);
1725
public Boolean visitLiteral(LiteralTree node, Void p) {
1727
col += tokens.token().length();
1728
} while (tokens.moveNext() && tokens.offset() < endPos);
1729
lastBlankLines = -1;
1730
lastBlankLinesTokenIndex = -1;
1731
lastBlankLinesDiff = null;
1736
public Boolean visitErroneous(ErroneousTree node, Void p) {
1737
for (Tree tree : node.getErrorTrees()) {
1738
int pos = (int)sp.getStartPosition(getCurrentPath().getCompilationUnit(), tree);
1740
col += tokens.token().length();
1741
} while (tokens.moveNext() && tokens.offset() < endPos);
1742
lastBlankLines = -1;
1743
lastBlankLinesTokenIndex = -1;
1744
lastBlankLinesDiff = null;
1748
col += tokens.token().length();
1749
} while (tokens.moveNext() && tokens.offset() < endPos);
1750
lastBlankLines = -1;
1751
lastBlankLinesTokenIndex = -1;
1752
lastBlankLinesDiff = null;
1757
public Boolean visitOther(Tree node, Void p) {
1759
col += tokens.token().length();
1760
} while (tokens.moveNext() && tokens.offset() < endPos);
1761
lastBlankLines = -1;
1762
lastBlankLinesTokenIndex = -1;
1763
lastBlankLinesDiff = null;
1767
private JavaTokenId accept(JavaTokenId first, JavaTokenId... rest) {
1768
lastBlankLines = -1;
1769
lastBlankLinesTokenIndex = -1;
1770
lastBlankLinesDiff = null;
1771
EnumSet<JavaTokenId> tokenIds = EnumSet.of(first, rest);
1772
Token<JavaTokenId> lastWSToken = null;
1775
if (tokens.offset() >= endPos)
1777
JavaTokenId id = tokens.token().id();
1778
if (tokenIds.contains(id)) {
1779
String spaces = after == 1 //after line comment
1781
: after == 2 //after javadoc comment
1782
? getNewlines(1) + getIndent()
1784
if (lastWSToken != null) {
1785
if (spaces == null || !spaces.contentEquals(lastWSToken.text()))
1786
diffs.addFirst(new Diff(tokens.offset() - lastWSToken.length(), tokens.offset(), spaces));
1788
if (spaces != null && spaces.length() > 0)
1789
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), spaces));
1793
col += tokens.token().length();
1794
return tokens.moveNext() ? id : null;
1798
lastWSToken = tokens.token();
1801
if (lastWSToken != null) {
1802
String spaces = after == 1 //after line comment
1804
: after == 2 //after javadoc comment
1805
? getNewlines(1) + getIndent()
1807
if (!spaces.contentEquals(lastWSToken.text()))
1808
diffs.addFirst(new Diff(tokens.offset() - lastWSToken.length(), tokens.offset(), spaces));
1811
String spaces = after == 1 //after line comment
1813
: after == 2 //after javadoc comment
1814
? getNewlines(1) + getIndent()
1816
if (spaces != null && spaces.length() > 0)
1817
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), spaces));
1820
after = 1; //line comment
1822
case JAVADOC_COMMENT:
1823
if (lastWSToken != null) {
1824
String spaces = after == 1 //after line comment
1826
: after == 2 //after javadoc comment
1827
? getNewlines(1) + getIndent()
1829
if (!spaces.contentEquals(lastWSToken.text()))
1830
diffs.addFirst(new Diff(tokens.offset() - lastWSToken.length(), tokens.offset(), spaces));
1837
String spaces = after == 1 //after line comment
1839
: after == 2 //after javadoc comment
1840
? getNewlines(1) + getIndent()
1842
if (spaces != null && spaces.length() > 0)
1843
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), spaces));
1847
String tokenText = tokens.token().text().toString();
1848
int idx = tokenText.lastIndexOf('\n'); //NOI18N
1850
tokenText = tokenText.substring(idx + 1);
1851
col += getCol(tokenText);
1853
after = 2; //javadoc comment
1856
if (lastWSToken != null) {
1857
String spaces = after == 1 //after line comment
1859
: after == 2 //after javadoc comment
1860
? getNewlines(1) + getIndent()
1862
if (!spaces.contentEquals(lastWSToken.text()))
1863
diffs.addFirst(new Diff(tokens.offset() - lastWSToken.length(), tokens.offset(), spaces));
1870
String spaces = after == 1 //after line comment
1872
: after == 2 //after javadoc comment
1873
? getNewlines(1) + getIndent()
1875
if (spaces != null && spaces.length() > 0)
1876
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), spaces));
1880
tokenText = tokens.token().text().toString();
1881
idx = tokenText.lastIndexOf('\n'); //NOI18N
1883
tokenText = tokenText.substring(idx + 1);
1884
col += getCol(tokenText);
1891
} while(tokens.moveNext());
1895
private void space() {
1899
private void spaces(int count) {
1900
spaces(count, false);
1903
private void spaces(int count, boolean preserveNewline) {
1904
Token<JavaTokenId> lastWSToken = null;
1907
if (tokens.offset() >= endPos)
1909
switch(tokens.token().id()) {
1911
lastWSToken = tokens.token();
1914
if (lastWSToken != null) {
1915
String spaces = after == 1 //after line comment
1917
: after == 2 //after javadoc comment
1918
? getNewlines(1) + getIndent()
1920
if (preserveNewline) {
1921
String text = lastWSToken.text().toString();
1922
int idx = text.lastIndexOf('\n'); //NOI18N
1924
spaces = getNewlines(1) + getIndent();
1926
if (spaces.indexOf('\n') >= 0) //NOI18N
1927
afterNewline = true;
1928
if (!spaces.contentEquals(lastWSToken.text()))
1929
diffs.addFirst(new Diff(tokens.offset() - lastWSToken.length(), tokens.offset(), spaces));
1932
String spaces = after == 1 //after line comment
1934
: after == 2 //after javadoc comment
1935
? getNewlines(1) + getIndent()
1937
if (spaces != null && spaces.indexOf('\n') >= 0) //NOI18N
1938
afterNewline = true;
1939
if (spaces != null && spaces.length() > 0)
1940
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), spaces));
1943
after = 1; //line comment
1945
case JAVADOC_COMMENT:
1946
if (lastWSToken != null) {
1947
String spaces = after == 1 //after line comment
1949
: after == 2 //after javadoc comment
1950
? getNewlines(1) + getIndent()
1952
if (preserveNewline) {
1953
String text = lastWSToken.text().toString();
1954
int idx = text.lastIndexOf('\n'); //NOI18N
1956
spaces = getNewlines(1) + getIndent();
1960
if (spaces.indexOf('\n') >= 0) //NOI18N
1961
afterNewline = true;
1962
if (!spaces.contentEquals(lastWSToken.text()))
1963
diffs.addFirst(new Diff(tokens.offset() - lastWSToken.length(), tokens.offset(), spaces));
1970
String spaces = after == 1 //after line comment
1972
: after == 2 //after javadoc comment
1973
? getNewlines(1) + getIndent()
1975
if (spaces != null && spaces.indexOf('\n') >= 0) //NOI18N
1976
afterNewline = true;
1977
if (spaces != null && spaces.length() > 0)
1978
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), spaces));
1982
String tokenText = tokens.token().text().toString();
1983
int idx = tokenText.lastIndexOf('\n'); //NOI18N
1985
tokenText = tokenText.substring(idx + 1);
1986
col += getCol(tokenText);
1988
after = 2; //javadoc comment
1991
if (lastWSToken != null) {
1992
String spaces = after == 1 //after line comment
1994
: after == 2 //after javadoc comment
1995
? getNewlines(1) + getIndent()
1997
if (preserveNewline) {
1998
String text = lastWSToken.text().toString();
1999
idx = text.lastIndexOf('\n'); //NOI18N
2001
spaces = getNewlines(1) + getIndent();
2005
if (spaces.indexOf('\n') >= 0) //NOI18N
2006
afterNewline = true;
2007
if (!spaces.contentEquals(lastWSToken.text()))
2008
diffs.addFirst(new Diff(tokens.offset() - lastWSToken.length(), tokens.offset(), spaces));
2015
String spaces = after == 1 //after line comment
2017
: after == 2 //after javadoc comment
2018
? getNewlines(1) + getIndent()
2020
if (spaces != null && spaces.indexOf('\n') >= 0) //NOI18N
2021
afterNewline = true;
2022
if (spaces != null && spaces.length() > 0)
2023
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), spaces));
2027
tokenText = tokens.token().text().toString();
2028
idx = tokenText.lastIndexOf('\n'); //NOI18N
2030
tokenText = tokenText.substring(idx + 1);
2031
col += getCol(tokenText);
2036
String spaces = after == 1 //after line comment
2038
: after == 2 //after javadoc comment
2039
? getNewlines(1) + getIndent()
2041
if (lastWSToken != null) {
2042
if (preserveNewline) {
2043
String text = lastWSToken.text().toString();
2044
idx = text.lastIndexOf('\n'); //NOI18N
2046
spaces = getNewlines(1) + getIndent();
2050
if (spaces.indexOf('\n') >= 0) //NOI18N
2051
afterNewline = true;
2052
if (!spaces.contentEquals(lastWSToken.text()))
2053
diffs.addFirst(new Diff(tokens.offset() - lastWSToken.length(), tokens.offset(), spaces));
2054
} else if (spaces.length() > 0) {
2055
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), spaces));
2063
} while(tokens.moveNext());
2066
private void newline() {
2070
private void blankLines() {
2071
blankLines(ANY_COUNT);
2074
private void blankLines(int count) {
2075
afterNewline = true;
2077
if (lastBlankLinesTokenIndex < 0) {
2078
lastBlankLines = count;
2079
lastBlankLinesTokenIndex = tokens.index();
2080
lastBlankLinesDiff = diffs.isEmpty() ? null : diffs.getFirst();
2081
} else if (lastBlankLines < count) {
2082
lastBlankLines = count;
2083
rollback(lastBlankLinesTokenIndex, lastBlankLinesTokenIndex, lastBlankLinesDiff);
2088
if (lastBlankLinesTokenIndex < 0) {
2089
lastBlankLinesTokenIndex = tokens.index();
2090
lastBlankLinesDiff = diffs.isEmpty() ? null : diffs.getFirst();
2095
Token<JavaTokenId> lastToken = null;
2098
if (tokens.offset() >= endPos)
2100
switch(tokens.token().id()) {
2102
lastToken = tokens.token();
2105
if (count >= 0 && tokens.index() > 1 && after != 1)
2107
if (lastToken != null) {
2108
int offset = tokens.offset() - lastToken.length();
2109
String text = lastToken.text().toString();
2112
while(count != 0 && (idx = text.indexOf('\n', lastIdx)) >= 0) { //NOI18N
2114
diffs.addFirst(new Diff(offset + lastIdx, offset + idx, null));
2118
if ((idx = text.lastIndexOf('\n')) >= 0) { //NOI18N
2120
diffs.addFirst(new Diff(offset + lastIdx, offset + idx + 1, null));
2124
String indent = getIndent();
2125
if (!indent.contentEquals(text.substring(lastIdx)))
2126
diffs.addFirst(new Diff(offset + lastIdx, tokens.offset(), indent));
2133
case JAVADOC_COMMENT:
2134
if (count >= 0 && tokens.index() > 1 && after != 1)
2136
if (lastToken != null) {
2137
int offset = tokens.offset() - lastToken.length();
2138
String text = lastToken.text().toString();
2141
while(count != 0 && (idx = text.indexOf('\n', lastIdx)) >= 0) { //NOI18N
2143
diffs.addFirst(new Diff(offset + lastIdx, offset + idx, null));
2147
if ((idx = text.lastIndexOf('\n')) >= 0) { //NOI18N
2150
diffs.addFirst(new Diff(offset + lastIdx, offset + idx + 1, null));
2153
if (lastIdx == 0 && count < 0) {
2154
count = count == ANY_COUNT ? 1 : 0;
2156
String indent = after == 3 ? SPACE : getNewlines(count) + getIndent();
2157
if (!indent.contentEquals(text.substring(lastIdx)))
2158
diffs.addFirst(new Diff(offset + lastIdx, tokens.offset(), indent));
2161
if (lastBlankLines < 0 && count == ANY_COUNT)
2162
count = lastBlankLines = 1;
2163
String text = getNewlines(count) + getIndent();
2164
if (text.length() > 0)
2165
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), text));
2172
if (lastToken != null) {
2173
if (count >= 0 && tokens.index() > 1 && after != 1)
2175
int offset = tokens.offset() - lastToken.length();
2176
String text = lastToken.text().toString();
2179
while(count != 0 && (idx = text.indexOf('\n', lastIdx)) >= 0) { //NOI18N
2181
diffs.addFirst(new Diff(offset + lastIdx, offset + idx, null));
2185
if ((idx = text.lastIndexOf('\n')) >= 0) { //NOI18N
2187
diffs.addFirst(new Diff(offset + lastIdx, offset + idx + 1, null));
2190
if (lastIdx == 0 && after == 1) {
2191
String indent = getIndent();
2192
if (!indent.contentEquals(text))
2193
diffs.addFirst(new Diff(offset, tokens.offset(), indent));
2194
} else if (lastIdx > 0 && lastIdx < lastToken.length()) {
2195
String indent = getIndent();
2196
if (!indent.contentEquals(text.substring(lastIdx)))
2197
diffs.addFirst(new Diff(offset + lastIdx, tokens.offset(), indent));
2206
if (count >= 0 && tokens.index() > 1 && after != 1)
2208
if (lastToken != null) {
2209
int offset = tokens.offset() - lastToken.length();
2210
String text = lastToken.text().toString();
2213
while(count != 0 && (idx = text.indexOf('\n', lastIdx)) >= 0) { //NOI18N
2215
diffs.addFirst(new Diff(offset + lastIdx, offset + idx, null));
2219
if ((idx = text.lastIndexOf('\n')) >= 0) { //NOI18N
2222
diffs.addFirst(new Diff(offset + lastIdx, offset + idx + 1, null));
2225
if (lastIdx == 0 && count < 0) {
2226
count = count == ANY_COUNT ? 1 : 0;
2228
String indent = after == 3 ? SPACE : getNewlines(count) + getIndent();
2229
if (!indent.contentEquals(text.substring(lastIdx)))
2230
diffs.addFirst(new Diff(offset + lastIdx, tokens.offset(), indent));
2232
if (lastBlankLines < 0 && count == ANY_COUNT)
2233
count = lastBlankLines = 1;
2234
String text = getNewlines(count) + getIndent();
2235
if (text.length() > 0)
2236
diffs.addFirst(new Diff(tokens.offset(), tokens.offset(), text));
2241
} while(tokens.moveNext());
2244
private void rollback(int index, int col, Diff diff) {
2245
tokens.moveIndex(index);
2250
while (!diffs.isEmpty() && diffs.getFirst() != diff)
2251
diffs.removeFirst();
2256
private int wrapToken(CodeStyle.WrapStyle wrapStyle, int spacesCnt, JavaTokenId first, JavaTokenId... rest) {
2258
switch (wrapStyle) {
2262
accept(first, rest);
2265
int index = tokens.index();
2267
Diff d = diffs.isEmpty() ? null : diffs.getFirst();
2268
spaces(spacesCnt, true);
2270
accept(first, rest);
2271
if (this.col > rightMargin) {
2272
rollback(index, c, d);
2275
accept(first, rest);
2279
spaces(spacesCnt, true);
2281
accept(first, rest);
2287
private int wrapTree(CodeStyle.WrapStyle wrapStyle, int spacesCnt, Tree tree) {
2289
switch (wrapStyle) {
2296
int index = tokens.index();
2298
Diff d = diffs.isEmpty() ? null : diffs.getFirst();
2299
spaces(spacesCnt, true);
2304
if (col > rightMargin && (wrapDepth == 0 || c <= rightMargin)) {
2305
rollback(index, c, d);
2312
spaces(spacesCnt, true);
2320
private boolean wrapStatement(CodeStyle.WrapStyle wrapStyle, CodeStyle.BracesGenerationStyle bracesGenerationStyle, int spacesCnt, StatementTree tree) {
2321
if (tree.getKind() == Tree.Kind.BLOCK) {
2322
if (bracesGenerationStyle == CodeStyle.BracesGenerationStyle.ELIMINATE) {
2323
Iterator<? extends StatementTree> stats = ((BlockTree)tree).getStatements().iterator();
2324
if (stats.hasNext()) {
2325
StatementTree stat = stats.next();
2326
if (!stats.hasNext() && stat.getKind() != Tree.Kind.VARIABLE) {
2327
int start = tokens.offset();
2330
while (!diffs.isEmpty() && (d = diffs.getFirst()) != null && d.getStartOffset() >= start)
2331
diffs.removeFirst();
2332
diffs.addFirst(new Diff(start, tokens.offset(), null));
2334
indent += indentSize;
2335
wrapTree(wrapStyle, spacesCnt, stat);
2337
start = tokens.offset();
2339
while (!diffs.isEmpty() && (d = diffs.getFirst()) != null && d.getStartOffset() >= start)
2340
diffs.removeFirst();
2341
diffs.addFirst(new Diff(start, tokens.offset(), null));
2349
if (bracesGenerationStyle == CodeStyle.BracesGenerationStyle.GENERATE) {
2350
scan(new FakeBlock(tree), null);
2354
indent += indentSize;
2355
int ret = wrapTree(wrapStyle, spacesCnt, tree);
2360
private void wrapList(CodeStyle.WrapStyle wrapStyle, boolean align, List<? extends Tree> trees) {
2361
boolean first = true;
2363
for (Iterator<? extends Tree> it = trees.iterator(); it.hasNext();) {
2364
Tree impl = it.next();
2370
wrapTree(wrapStyle, cs.spaceAfterComma() ? 1 : 0, impl);
2374
spaces(cs.spaceBeforeComma() ? 1 : 0);
2381
private void indentComment() {
2382
if (tokens.token().id() != BLOCK_COMMENT && tokens.token().id() != JAVADOC_COMMENT)
2384
String indent = getIndent();
2385
String text = tokens.token().text().toString();
2387
while ((idx = text.indexOf('\n', idx)) >= 0) { //NOI18N
2389
while(text.charAt(i) <= ' ') //NOI18N
2391
String s = text.charAt(i) == '*' ? indent + SPACE : indent;
2392
if (!s.equals(text.substring(idx + 1, i)))
2393
diffs.addFirst(new Diff(tokens.offset() + idx + 1, tokens.offset() + i, s)); //NOI18N
2398
private String getSpaces(int count) {
2403
StringBuilder sb = new StringBuilder();
2405
sb.append(' '); //NOI18N
2406
return sb.toString();
2409
private String getNewlines(int count) {
2414
StringBuilder sb = new StringBuilder();
2416
sb.append('\n'); //NOI18N
2417
return sb.toString();
2420
private String getIndent() {
2421
StringBuilder sb = new StringBuilder();
2423
if (!expandTabToSpaces) {
2424
while (((col + tabSize) &~ (tabSize - 1)) <= indent) {
2425
sb.append('\t'); //NOI18N
2426
col = col + tabSize & ~(tabSize - 1);
2429
while (col < indent) {
2430
sb.append(SPACE); //NOI18N
2433
return sb.toString();
2436
private int getIndentLevel(CompilationInfo info, TreePath path) {
2437
TokenSequence<JavaTokenId> tokens = info.getTokenHierarchy().tokenSequence(JavaTokenId.language());
2440
if (path.getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT)
2443
Tree lastTree = null;
2444
while (path != null) {
2445
int offset = (int)sp.getStartPosition(path.getCompilationUnit(), path.getLeaf());
2448
tokens.move(offset);
2449
if (tokens.movePrevious()) {
2450
Token<JavaTokenId> token = tokens.token();
2451
if (token.id() == WHITESPACE) {
2452
String text = token.text().toString();
2453
int idx = text.lastIndexOf('\n');
2455
text = text.substring(idx + 1);
2456
indent = getCol(text);
2458
} else if (tokens.movePrevious()) {
2459
if (tokens.token().id() == LINE_COMMENT) {
2460
indent = getCol(text);
2466
lastTree = path.getLeaf();
2467
path = path.getParentPath();
2469
if (lastTree != null && path != null) {
2470
switch (path.getLeaf().getKind()) {
2472
for (Tree tree : ((ClassTree)path.getLeaf()).getMembers()) {
2473
if (tree == lastTree) {
2480
for (Tree tree : ((BlockTree)path.getLeaf()).getStatements()) {
2481
if (tree == lastTree) {
2492
private int getCol(String text) {
2494
for (int i = 0; i < text.length(); i++) {
2495
char c = text.charAt(i);
2497
col = col+tabSize & ~(tabSize-1);
2505
private boolean isEnumerator(VariableTree tree) {
2506
return (((JCModifiers)tree.getModifiers()).flags & Flags.ENUM) != 0;
2509
private boolean isSynthetic(CompilationUnitTree cut, Tree leaf) {
2510
JCTree tree = (JCTree) leaf;
2511
if (tree.pos == (-1))
2513
if (leaf.getKind() == Tree.Kind.METHOD) {
2514
//check for synthetic constructor:
2515
return (((JCMethodDecl)leaf).mods.flags & Flags.GENERATEDCONSTR) != 0L;
2517
//check for synthetic superconstructor call:
2518
if (leaf.getKind() == Tree.Kind.EXPRESSION_STATEMENT) {
2519
ExpressionStatementTree est = (ExpressionStatementTree) leaf;
2520
if (est.getExpression().getKind() == Tree.Kind.METHOD_INVOCATION) {
2521
MethodInvocationTree mit = (MethodInvocationTree) est.getExpression();
2522
if (mit.getMethodSelect().getKind() == Tree.Kind.IDENTIFIER) {
2523
IdentifierTree it = (IdentifierTree) mit.getMethodSelect();
2524
if ("super".equals(it.getName().toString())) {
2525
return sp.getEndPosition(cut, leaf) == (-1);
2533
private static class FakeBlock extends JCBlock {
2535
private StatementTree stat;
2537
private FakeBlock(StatementTree stat) {
2538
super(0L, com.sun.tools.javac.util.List.of((JCStatement)stat));
2544
private static class Diff {
2547
private String text;
2549
private Diff(int start, int end, String text) {
2555
public int getStartOffset() {
2559
public int getEndOffset() {
2563
public String getText() {
2568
public String toString() {
2569
return "Diff<" + start + "," + end + ">:" + text; //NOI18N