Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 6e936b1a0a5db61a7fc27fd45d3d65674f21dc89 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 * 
 * 
 * This is an implementation of an early-draft specification developed under the Java
 * Community Process (JCP) and is made available for testing and evaluation purposes
 * only. The code is not compatible with any specification of the JCP.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.core.dom.rewrite;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.formatter.IndentManipulation;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.DefaultPositionUpdater;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.Position;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;

@SuppressWarnings({"rawtypes", "unchecked"})
public final class ASTRewriteFormatter {

	public static class NodeMarker extends Position {
		public Object data;
	}

	private class ExtendedFlattener extends ASTRewriteFlattener {

		private ArrayList positions;

		public ExtendedFlattener(RewriteEventStore store) {
			super(store);
			this.positions= new ArrayList();
		}

		@Override
		public void preVisit(ASTNode node) {
			Object trackData= getEventStore().getTrackedNodeData(node);
			if (trackData != null) {
				addMarker(trackData, this.result.length(), 0);
			}
			Object placeholderData= getPlaceholders().getPlaceholderData(node);
			if (placeholderData != null) {
				addMarker(placeholderData, this.result.length(), 0);
			}
		}

		@Override
		public void postVisit(ASTNode node) {
			Object placeholderData= getPlaceholders().getPlaceholderData(node);
			if (placeholderData != null) {
				fixupLength(placeholderData, this.result.length());
			}
			Object trackData= getEventStore().getTrackedNodeData(node);
			if (trackData != null) {
				fixupLength(trackData, this.result.length());
			}
		}

		@Override
		public boolean visit(Block node) {
			if (getPlaceholders().isCollapsed(node)) {
				visitList(node, Block.STATEMENTS_PROPERTY, null);
				return false;
			}
			return super.visit(node);
		}

		private NodeMarker addMarker(Object annotation, int startOffset, int length) {
			NodeMarker marker= new NodeMarker();
			marker.offset= startOffset;
			marker.length= length;
			marker.data= annotation;
			this.positions.add(marker);
			return marker;
		}

		private void fixupLength(Object data, int endOffset) {
			for (int i= this.positions.size()-1; i >= 0 ; i--) {
				NodeMarker marker= (NodeMarker) this.positions.get(i);
				if (marker.data == data) {
					marker.length= endOffset - marker.offset;
					return;
				}
			}
		}

		public NodeMarker[] getMarkers() {
			return (NodeMarker[]) this.positions.toArray(new NodeMarker[this.positions.size()]);
		}
	}

	private final String lineDelimiter;
	private final int tabWidth;
	private final int indentWidth;

	private final NodeInfoStore placeholders;
	private final RewriteEventStore eventStore;

	private final Map options;


	public ASTRewriteFormatter(NodeInfoStore placeholders, RewriteEventStore eventStore, Map options, String lineDelimiter) {
		this.placeholders= placeholders;
		this.eventStore= eventStore;
	
		this.options= options == null ? JavaCore.getOptions() : (Map) new HashMap(options);
		this.options.put(
				DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_RESOURCES_IN_TRY,
				DefaultCodeFormatterConstants.createAlignmentValue(true, DefaultCodeFormatterConstants.WRAP_NEXT_PER_LINE, DefaultCodeFormatterConstants.INDENT_DEFAULT));

		this.lineDelimiter= lineDelimiter;
	
		this.tabWidth= IndentManipulation.getTabWidth(options);
		this.indentWidth= IndentManipulation.getIndentWidth(options);
	}



	public NodeInfoStore getPlaceholders() {
		return this.placeholders;
	}

	public RewriteEventStore getEventStore() {
		return this.eventStore;
	}

	public int getTabWidth() {
		return this.tabWidth;
	}

	public int getIndentWidth() {
		return this.indentWidth;
	}

	public String getLineDelimiter() {
		return this.lineDelimiter;
	}

	/**
	 * Returns the string accumulated in the visit formatted using the default formatter.
	 * Updates the existing node's positions.
	 *
	 * @param node The node to flatten.
	 * @param initialIndentationLevel The initial indentation level.
	 * @param resultingMarkers Resulting the updated NodeMarkers.
	 * @return Returns the serialized and formatted code.
	 */
	public String getFormattedResult(ASTNode node, int initialIndentationLevel, Collection resultingMarkers) {

		ExtendedFlattener flattener= new ExtendedFlattener(this.eventStore);
		node.accept(flattener);

		NodeMarker[] markers= flattener.getMarkers();
		for (int i= 0; i < markers.length; i++) {
			resultingMarkers.add(markers[i]); // add to result
		}

		String unformatted= flattener.getResult();
		TextEdit edit= formatNode(node, unformatted, initialIndentationLevel);
		if (edit == null) {
		    if (initialIndentationLevel > 0) {
		        // at least correct the indent
		        String indentString = createIndentString(initialIndentationLevel);
				ReplaceEdit[] edits = IndentManipulation.getChangeIndentEdits(unformatted, 0, this.tabWidth, this.indentWidth, indentString);
				edit= new MultiTextEdit();
				edit.addChild(new InsertEdit(0, indentString));
				edit.addChildren(edits);
		    } else {
		       return unformatted;
		    }
		}
		return evaluateFormatterEdit(unformatted, edit, markers);
	}

    public String createIndentString(int indentationUnits) {
    	return ToolFactory.createCodeFormatter(this.options).createIndentationString(indentationUnits);
    }

	public String getIndentString(String currentLine) {
		return IndentManipulation.extractIndentString(currentLine, this.tabWidth, this.indentWidth);
	}

	public String changeIndent(String code, int codeIndentLevel, String newIndent) {
		return IndentManipulation.changeIndent(code, codeIndentLevel, this.tabWidth, this.indentWidth, newIndent, this.lineDelimiter);
	}

	public int computeIndentUnits(String line) {
		return IndentManipulation.measureIndentUnits(line, this.tabWidth, this.indentWidth);
	}

	/**
	 * Evaluates the edit on the given string.
	 * @param string The string to format
	 * @param edit The edit resulted from the code formatter
	 * @param positions Positions to update or <code>null</code>.
	 * @return The formatted string
	 * @throws IllegalArgumentException If the positions are not inside the string, a
	 *  IllegalArgumentException is thrown.
	 */
	public static String evaluateFormatterEdit(String string, TextEdit edit, Position[] positions) {
		try {
			Document doc= createDocument(string, positions);
			edit.apply(doc, 0);
			if (positions != null) {
				for (int i= 0; i < positions.length; i++) {
					Assert.isTrue(!positions[i].isDeleted, "Position got deleted"); //$NON-NLS-1$
				}
			}
			return doc.get();
		} catch (BadLocationException e) {
			//JavaPlugin.log(e); // bug in the formatter
			Assert.isTrue(false, "Fromatter created edits with wrong positions: " + e.getMessage()); //$NON-NLS-1$
		}
		return null;
	}

	public TextEdit formatString(int kind, String string, int offset, int length, int indentationLevel) {
		return ToolFactory.createCodeFormatter(this.options).format(kind, string, offset, length, indentationLevel, this.lineDelimiter);
	}

	/**
	 * Creates edits that describe how to format the given string. Returns <code>null</code> if the code could not be formatted for the given kind.
	 * @param node Node describing the type of the string
	 * @param str The unformatted string
	 * @param indentationLevel
	 * @return Returns the edit representing the result of the formatter
	 * @throws IllegalArgumentException If the offset and length are not inside the string, a
	 *  IllegalArgumentException is thrown.
	 */
	private TextEdit formatNode(ASTNode node, String str, int indentationLevel) {
		int code;
		String prefix= ""; //$NON-NLS-1$
		String suffix= ""; //$NON-NLS-1$
		if (node instanceof Statement) {
			code= CodeFormatter.K_STATEMENTS;
			if (node.getNodeType() == ASTNode.SWITCH_CASE) {
				prefix= "switch(1) {"; //$NON-NLS-1$
				suffix= "}"; //$NON-NLS-1$
				code= CodeFormatter.K_STATEMENTS;
			}
		} else if (node instanceof Expression && node.getNodeType() != ASTNode.VARIABLE_DECLARATION_EXPRESSION) {
			if (node instanceof Annotation) {
				suffix= "\nclass A {}"; //$NON-NLS-1$
				code= CodeFormatter.K_COMPILATION_UNIT;
			} else {
				code= CodeFormatter.K_EXPRESSION;
			}
		} else if (node instanceof BodyDeclaration) {
			code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
		} else {
			switch (node.getNodeType()) {
				case ASTNode.ARRAY_TYPE:
				case ASTNode.PARAMETERIZED_TYPE:
				case ASTNode.PRIMITIVE_TYPE:
				case ASTNode.QUALIFIED_TYPE:
				case ASTNode.SIMPLE_TYPE:
					prefix= "void m(final "; //$NON-NLS-1$
					suffix= " x);"; //$NON-NLS-1$
					code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
					break;
				case ASTNode.WILDCARD_TYPE:
					prefix= "A<"; //$NON-NLS-1$
					suffix= "> x;"; //$NON-NLS-1$
					code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
					break;
				case ASTNode.COMPILATION_UNIT:
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.MODULE_DECLARATION:
					code= CodeFormatter.K_MODULE_INFO;
					break;
				case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
					suffix= ";"; //$NON-NLS-1$
					code= CodeFormatter.K_STATEMENTS;
					break;
				case ASTNode.SINGLE_VARIABLE_DECLARATION:
					prefix= "void m("; //$NON-NLS-1$
					suffix= ");"; //$NON-NLS-1$
					code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
					break;
				case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
					prefix= "A "; //$NON-NLS-1$
					suffix= ";"; //$NON-NLS-1$
					code= CodeFormatter.K_STATEMENTS;
					break;
				case ASTNode.PACKAGE_DECLARATION:
				case ASTNode.IMPORT_DECLARATION:
					suffix= "\nclass A {}"; //$NON-NLS-1$
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.JAVADOC:
					suffix= "\nclass A {}"; //$NON-NLS-1$
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.CATCH_CLAUSE:
					prefix= "try {}"; //$NON-NLS-1$
					code= CodeFormatter.K_STATEMENTS;
					break;
				case ASTNode.ANONYMOUS_CLASS_DECLARATION:
					prefix= "new A()"; //$NON-NLS-1$
					suffix= ";"; //$NON-NLS-1$
					code= CodeFormatter.K_STATEMENTS;
					break;
				case ASTNode.MEMBER_VALUE_PAIR:
					prefix= "@Author("; //$NON-NLS-1$
					suffix= ") class x {}"; //$NON-NLS-1$
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.MODIFIER:
					suffix= " class x {}"; //$NON-NLS-1$
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.MODULE_MODIFIER:
					code= CodeFormatter.K_MODULE_INFO;
					break;
				case ASTNode.TYPE_PARAMETER:
					prefix= "class X<"; //$NON-NLS-1$
					suffix= "> {}"; //$NON-NLS-1$
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.MEMBER_REF:
				case ASTNode.METHOD_REF:
				case ASTNode.METHOD_REF_PARAMETER:
				case ASTNode.TAG_ELEMENT:
				case ASTNode.TEXT_ELEMENT:
					// javadoc formatting disabled due to bug 93644
					return null;

//				wiat for bug 93644
//				case ASTNode.MEMBER_REF:
//				case ASTNode.METHOD_REF:
//					prefix= "/**\n * @see ";
//					suffix= "\n*/";
//					code= CodeFormatter.K_JAVA_DOC;
//					break;
//				case ASTNode.METHOD_REF_PARAMETER:
//					prefix= "/**\n * @see A#foo(";
//					suffix= ")\n*/";
//					code= CodeFormatter.K_JAVA_DOC;
//					break;
//				case ASTNode.TAG_ELEMENT:
//				case ASTNode.TEXT_ELEMENT:
//					prefix= "/**\n * ";
//					suffix= "\n*/";
//					code= CodeFormatter.K_JAVA_DOC;
//					break;
				default:
					//Assert.isTrue(false, "Node type not covered: " + node.getClass().getName());
					return null;
			}
		}

		String concatStr= prefix + str + suffix;
		TextEdit edit= formatString(code, concatStr, prefix.length(), str.length(), indentationLevel);

		if (prefix.length() > 0) {
			edit= shifEdit(edit, prefix.length());
		}
		return edit;
	}

	private static TextEdit shifEdit(TextEdit oldEdit, int diff) {
		TextEdit newEdit;
		if (oldEdit instanceof ReplaceEdit) {
			ReplaceEdit edit= (ReplaceEdit) oldEdit;
			newEdit= new ReplaceEdit(edit.getOffset() - diff, edit.getLength(), edit.getText());
		} else if (oldEdit instanceof InsertEdit) {
			InsertEdit edit= (InsertEdit) oldEdit;
			newEdit= new InsertEdit(edit.getOffset() - diff,  edit.getText());
		} else if (oldEdit instanceof DeleteEdit) {
			DeleteEdit edit= (DeleteEdit) oldEdit;
			newEdit= new DeleteEdit(edit.getOffset() - diff,  edit.getLength());
		} else if (oldEdit instanceof MultiTextEdit) {
			newEdit= new MultiTextEdit();
		} else {
			return null; // not supported
		}
		TextEdit[] children= oldEdit.getChildren();
		for (int i= 0; i < children.length; i++) {
			TextEdit shifted= shifEdit(children[i], diff);
			if (shifted != null) {
				newEdit.addChild(shifted);
			}
		}
		return newEdit;
	}

	private static Document createDocument(String string, Position[] positions) throws IllegalArgumentException {
		Document doc= new Document(string);
		try {
			if (positions != null) {
				final String POS_CATEGORY= "myCategory"; //$NON-NLS-1$

				doc.addPositionCategory(POS_CATEGORY);
				doc.addPositionUpdater(new DefaultPositionUpdater(POS_CATEGORY) {
					@Override
					protected boolean notDeleted() {
						int start= this.fOffset;
						int end= start + this.fLength;
						if (start < this.fPosition.offset && (this.fPosition.offset + this.fPosition.length < end)) {
							this.fPosition.offset= end; // deleted positions: set to end of remove
							return false;
						}
						return true;
					}
				});
				for (int i= 0; i < positions.length; i++) {
					try {
						doc.addPosition(POS_CATEGORY, positions[i]);
					} catch (BadLocationException e) {
						throw new IllegalArgumentException("Position outside of string. offset: " + positions[i].offset + ", length: " + positions[i].length + ", string size: " + string.length(), e);   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
					}
				}
			}
		} catch (BadPositionCategoryException cannotHappen) {
			// can not happen: category is correctly set up
		}
		return doc;
	}



    public static interface Prefix {
		String getPrefix(int indent);
	}

	public static interface BlockContext {
		String[] getPrefixAndSuffix(int indent, ASTNode node, RewriteEventStore events);
	}

	public static class ConstPrefix implements Prefix {
		private String prefix;

		public ConstPrefix(String prefix) {
			this.prefix= prefix;
		}

		@Override
		public String getPrefix(int indent) {
			return this.prefix;
		}
	}

	private class FormattingPrefix implements Prefix {
		private int kind;
		private String string;
		private int start;
		private int length;

		public FormattingPrefix(String string, String sub, int kind) {
			this.start= string.indexOf(sub);
			this.length= sub.length();
			this.string= string;
			this.kind= kind;
		}

		@Override
		public String getPrefix(int indent) {
			Position pos= new Position(this.start, this.length);
			String str= this.string;
			TextEdit res= formatString(this.kind, str, 0, str.length(), indent);
			if (res != null) {
				str= evaluateFormatterEdit(str, res, new Position[] { pos });
			}
			return str.substring(pos.offset + 1, pos.offset + pos.length - 1);
		}
	}

	private class BlockFormattingPrefix implements BlockContext {
		private String prefix;
		private int start;

		public BlockFormattingPrefix(String prefix, int start) {
			this.start= start;
			this.prefix= prefix;
		}

		@Override
		public String[] getPrefixAndSuffix(int indent, ASTNode node, RewriteEventStore events) {
			String nodeString= ASTRewriteFlattener.asString(node, events);
			String str= this.prefix + nodeString;
			Position pos= new Position(this.start, this.prefix.length() + 1 - this.start);

			TextEdit res= formatString(CodeFormatter.K_STATEMENTS, str, 0, str.length(), indent);
			if (res != null) {
				str= evaluateFormatterEdit(str, res, new Position[] { pos });
			}
			return new String[] { str.substring(pos.offset + 1, pos.offset + pos.length - 1), ""}; //$NON-NLS-1$
		}
	}

	private class BlockFormattingPrefixSuffix implements BlockContext {
		private String prefix;
		private String suffix;
		private int start;

		public BlockFormattingPrefixSuffix(String prefix, String suffix, int start) {
			this.start= start;
			this.suffix= suffix;
			this.prefix= prefix;
		}

		@Override
		public String[] getPrefixAndSuffix(int indent, ASTNode node, RewriteEventStore events) {
			String nodeString= ASTRewriteFlattener.asString(node, events);
			int nodeStart= this.prefix.length();
			int nodeEnd= nodeStart + nodeString.length() - 1;

			String str= this.prefix + nodeString + this.suffix;

			Position pos1= new Position(this.start, nodeStart + 1 - this.start);
			Position pos2= new Position(nodeEnd, 2);

			TextEdit res= formatString(CodeFormatter.K_STATEMENTS, str, 0, str.length(), indent);
			if (res != null) {
				str= evaluateFormatterEdit(str, res, new Position[] { pos1, pos2 });
			}
			return new String[] {
				str.substring(pos1.offset + 1, pos1.offset + pos1.length - 1),
				str.substring(pos2.offset + 1, pos2.offset + pos2.length - 1)
			};
		}
	}

	public final static Prefix NONE= new ConstPrefix(""); //$NON-NLS-1$
	public final static Prefix SPACE= new ConstPrefix(" "); //$NON-NLS-1$
	public final static Prefix ASSERT_COMMENT= new ConstPrefix(" : "); //$NON-NLS-1$

	public final Prefix VAR_INITIALIZER= new FormattingPrefix("A a={};", "a={" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix METHOD_BODY= new FormattingPrefix("void a() {}", ") {" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix FINALLY_BLOCK= new FormattingPrefix("try {} finally {}", "} finally {", CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix CATCH_BLOCK= new FormattingPrefix("try {} catch(Exception e) {}", "} c" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix ANNOT_MEMBER_DEFAULT= new FormattingPrefix("String value() default 1;", ") default 1" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix ENUM_BODY_START= new FormattingPrefix("enum E { A(){void foo(){}} }", "){v" , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix ENUM_BODY_END= new FormattingPrefix("enum E { A(){void foo(){ }}, B}", "}}," , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix WILDCARD_EXTENDS= new FormattingPrefix("A<? extends B> a;", "? extends B" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix WILDCARD_SUPER= new FormattingPrefix("A<? super B> a;", "? super B" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$

	public final Prefix FIRST_ENUM_CONST= new FormattingPrefix("enum E { X;}", "{ X" , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix ANNOTATION_SEPARATION= new FormattingPrefix("@A @B class C {}", "A @" , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix PARAM_ANNOTATION_SEPARATION= new FormattingPrefix("void foo(@A @B C p) { }", "A @" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix LOCAL_ANNOTATION_SEPARATION= new FormattingPrefix("@A @B C p;", "A @" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix TYPE_ANNOTATION_SEPARATION= new FormattingPrefix("C<@A @B D> l;", "A @" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix VARARGS= new FormattingPrefix("void foo(A ... a) { }", "A ." , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix TRY_RESOURCES = new FormattingPrefix("try (A a = new A(); B b = new B()) {}", "; B" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix TRY_RESOURCES_PAREN = new FormattingPrefix("try (A a = new A(); B b = new B()) {}", "y (" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	
	public final BlockContext IF_BLOCK_WITH_ELSE= new BlockFormattingPrefixSuffix("if (true)", "else{}", 8); //$NON-NLS-1$ //$NON-NLS-2$
	public final BlockContext IF_BLOCK_NO_ELSE= new BlockFormattingPrefix("if (true)", 8); //$NON-NLS-1$
	public final BlockContext ELSE_AFTER_STATEMENT= new BlockFormattingPrefix("if (true) foo();else ", 15); //$NON-NLS-1$
	public final BlockContext ELSE_AFTER_BLOCK= new BlockFormattingPrefix("if (true) {}else ", 11); //$NON-NLS-1$
	
	public final Prefix CASE_SEPARATION= new FormattingPrefix("case A, B", "A" , CodeFormatter.K_EXPRESSION); //$NON-NLS-1$ //$NON-NLS-2$

	public final BlockContext FOR_BLOCK= new BlockFormattingPrefix("for (;;) ", 7); //$NON-NLS-1$
	public final BlockContext WHILE_BLOCK= new BlockFormattingPrefix("while (true)", 11); //$NON-NLS-1$
	public final BlockContext DO_BLOCK= new BlockFormattingPrefixSuffix("do ", "while (true);", 1); //$NON-NLS-1$ //$NON-NLS-2$

}

Back to the top