001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * Alex Blewitt - alex_blewitt@yahoo.com https://bugs.eclipse.org/bugs/show_bug.cgi?id=171066
011: *******************************************************************************/package org.eclipse.jdt.core.util;
012:
013: import java.util.Comparator;
014:
015: import org.eclipse.core.runtime.IProgressMonitor;
016: import org.eclipse.jdt.core.ICompilationUnit;
017: import org.eclipse.jdt.core.IJavaElement;
018: import org.eclipse.jdt.core.JavaModelException;
019: import org.eclipse.jdt.core.dom.AST;
020: import org.eclipse.jdt.core.dom.CompilationUnit;
021: import org.eclipse.jdt.internal.core.SortElementsOperation;
022: import org.eclipse.text.edits.TextEdit;
023: import org.eclipse.text.edits.TextEditGroup;
024:
025: /**
026: * Operation for sorting members within a compilation unit.
027: * <p>
028: * This class provides all functionality via static members; it is not
029: * intended to be instantiated or subclassed.
030: * </p>
031: *
032: * @since 2.1
033: */
034: public final class CompilationUnitSorter {
035:
036: /**
037: * Private constructor to prevent instantiation.
038: */
039: private CompilationUnitSorter() {
040: // Not instantiable
041: }
042:
043: /**
044: * @deprecated marking deprecated as it is using deprecated code
045: */
046: private static void checkASTLevel(int level) {
047: switch (level) {
048: case AST.JLS2:
049: case AST.JLS3:
050: break;
051: default:
052: throw new IllegalArgumentException();
053: }
054: }
055:
056: /**
057: * Name of auxillary property whose value can be used to determine the
058: * original relative order of two body declarations. This allows a
059: * comparator to preserve the relative positions of certain kinds of
060: * body declarations when required.
061: * <p>
062: * All body declarations passed to the comparator's <code>compare</code>
063: * method by <code>CompilationUnitSorter.sort</code> carry an
064: * Integer-valued property. The body declaration with the lower value
065: * comes before the one with the higher value. The exact numeric value
066: * of these properties is unspecified.
067: * </p>
068: * <p>
069: * Example usage:
070: * <pre>
071: * BodyDeclaration b1 = (BodyDeclaration) object1;
072: * BodyDeclaration b2 = (BodyDeclaration) object2;
073: * Integer i1 = (Integer) b1.getProperty(RELATIVE_ORDER);
074: * Integer i2 = (Integer) b2.getProperty(RELATIVE_ORDER);
075: * return i1.intValue() - i2.intValue(); // preserve original order
076: * </pre>
077: * </p>
078: *
079: * @see #sort(ICompilationUnit, int[], Comparator, int, IProgressMonitor)
080: * @see org.eclipse.jdt.core.dom.BodyDeclaration
081: */
082: public static final String RELATIVE_ORDER = "relativeOrder"; //$NON-NLS-1$
083:
084: /**
085: * Reorders the declarations in the given compilation unit according to
086: * JLS2 rules. The caller is
087: * responsible for arranging in advance that the given compilation unit is
088: * a working copy, and for saving the changes afterwards.
089: * <p>
090: * <b>Note:</b> Reordering the members within a type declaration might be
091: * more than a cosmetic change and could have potentially serious
092: * repercussions. Firstly, the order in which the fields of a type are
093: * initialized is significant in the Java language; reordering fields
094: * and initializers may result in compilation errors or change the execution
095: * behavior of the code. Secondly, reordering a class's members may affect
096: * how its instances are serialized. This operation should therefore be used
097: * with caution and due concern for potential negative side effects.
098: * </p>
099: * <p>
100: * The optional <code>positions</code> array contains a non-decreasing
101: * ordered list of character-based source positions within the compilation
102: * unit's source code string. Upon return from this method, the positions in
103: * the array reflect the corresponding new locations in the modified source
104: * code string. Note that this operation modifies the given array in place.
105: * </p>
106: * <p>
107: * The <code>compare</code> method of the given comparator is passed pairs
108: * of JLS2 AST body declarations (subclasses of <code>BodyDeclaration</code>)
109: * representing body declarations at the same level. The comparator is
110: * called on body declarations of nested classes, including anonymous and
111: * local classes, but always at the same level. Clients need to provide
112: * a comparator implementation (there is no standard comparator). The
113: * <code>RELATIVE_ORDER</code> property attached to these AST nodes afforts
114: * the comparator a way to preserve the original relative order.
115: * </p>
116: * <p>
117: * The body declarations passed as parameters to the comparator
118: * always carry at least the following minimal signature information:
119: * <br>
120: * <table border="1" width="80%" cellpadding="5">
121: * <tr>
122: * <td width="20%"><code>TypeDeclaration</code></td>
123: * <td width="50%"><code>modifiers, isInterface, name, superclass,
124: * superInterfaces<br>
125: * RELATIVE_ORDER property</code></td>
126: * </tr>
127: * <tr>
128: * <td width="20%"><code>FieldDeclaration</code></td>
129: * <td width="50%"><code>modifiers, type, fragments
130: * (VariableDeclarationFragments
131: * with name only)<br>
132: * RELATIVE_ORDER property</code></td>
133: * </tr>
134: * <tr>
135: * <td width="20%"><code>MethodDeclaration</code></td>
136: * <td width="50%"><code>modifiers, isConstructor, returnType, name,
137: * parameters
138: * (SingleVariableDeclarations with name and type only),
139: * thrownExceptions<br>
140: * RELATIVE_ORDER property</code></td>
141: * </tr>
142: * <tr>
143: * <td width="20%"><code>Initializer</code></td>
144: * <td width="50%"><code>modifiers<br>
145: * RELATIVE_ORDER property</code></td>
146: * </tr>
147: * </table>
148: * Clients should not rely on the AST nodes being properly parented or on
149: * having source range information. (Future releases may provide options
150: * for requesting additional information like source positions, full ASTs,
151: * non-recursive sorting, etc.)
152: * </p>
153: *
154: * @param compilationUnit the given compilation unit, which must be a
155: * working copy
156: * @param positions an array of source positions to map, or
157: * <code>null</code> if none. If supplied, the positions must
158: * character-based source positions within the original source code for
159: * the given compilation unit, arranged in non-decreasing order.
160: * The array is updated in place when this method returns to reflect the
161: * corresponding source positions in the permuted source code string
162: * (but not necessarily any longer in non-decreasing order).
163: * @param comparator the comparator capable of ordering
164: * <code>BodyDeclaration</code>s; this comparator is passed AST nodes
165: * from a JLS2 AST
166: * @param options bitwise-or of option flags; <code>0</code> for default
167: * behavior (reserved for future growth)
168: * @param monitor the progress monitor to notify, or <code>null</code> if
169: * none
170: * @exception JavaModelException if the compilation unit could not be
171: * sorted. Reasons include:
172: * <ul>
173: * <li> The given compilation unit does not exist (ELEMENT_DOES_NOT_EXIST)</li>
174: * <li> The given compilation unit is not a working copy (INVALID_ELEMENT_TYPES)</li>
175: * <li> A <code>CoreException</code> occurred while accessing the underlying
176: * resource
177: * </ul>
178: * @exception IllegalArgumentException if the given compilation unit is null
179: * or if the given comparator is null.
180: * @see org.eclipse.jdt.core.dom.BodyDeclaration
181: * @see #RELATIVE_ORDER
182: * @deprecated Clients should port their code to use the new JLS3 AST API and call
183: * {@link #sort(int, ICompilationUnit, int[], Comparator, int, IProgressMonitor)
184: * CompilationUnitSorter.sort(AST.JLS3, compilationUnit, positions, comparator, options, monitor)}
185: * instead of using this method.
186: */
187: public static void sort(ICompilationUnit compilationUnit,
188: int[] positions, Comparator comparator, int options,
189: IProgressMonitor monitor) throws JavaModelException {
190: sort(AST.JLS2, compilationUnit, positions, comparator, options,
191: monitor);
192: }
193:
194: /**
195: * Reorders the declarations in the given compilation unit according to
196: * the specified AST level. The caller is responsible for arranging in
197: * advance that the given compilation unit is a working copy, and for
198: * saving the changes afterwards.
199: * <p>
200: * <b>Note:</b> Reordering the members within a type declaration might be
201: * more than a cosmetic change and could have potentially serious
202: * repercussions. Firstly, the order in which the fields of a type are
203: * initialized is significant in the Java language; reordering fields
204: * and initializers may result in compilation errors or change the execution
205: * behavior of the code. Secondly, reordering a class's members may affect
206: * how its instances are serialized. This operation should therefore be used
207: * with caution and due concern for potential negative side effects.
208: * </p>
209: * <p>
210: * The optional <code>positions</code> array contains a non-decreasing
211: * ordered list of character-based source positions within the compilation
212: * unit's source code string. Upon return from this method, the positions in
213: * the array reflect the corresponding new locations in the modified source
214: * code string. Note that this operation modifies the given array in place.
215: * </p>
216: * <p>
217: * The <code>compare</code> method of the given comparator is passed pairs
218: * of body declarations (subclasses of <code>BodyDeclaration</code>)
219: * representing body declarations at the same level. The nodes are from an
220: * AST of the specified level
221: * ({@link org.eclipse.jdt.core.dom.ASTParser#newParser(int)}. Clients
222: * will generally specify AST.JLS3 since that will cover all constructs found
223: * in Java 1.0, 1.1, 1.2, 1.3, 1.4, and 1.5 source code.
224: * The comparator is called on body declarations of nested classes, including
225: * anonymous and local classes, but always at the same level. Clients need to provide
226: * a comparator implementation (there is no standard comparator). The
227: * <code>RELATIVE_ORDER</code> property attached to these AST nodes afforts
228: * the comparator a way to preserve the original relative order.
229: * </p>
230: * <p>
231: * The body declarations passed as parameters to the comparator
232: * always carry at least the following minimal signature information:
233: * <br>
234: * <table border="1" width="80%" cellpadding="5">
235: * <tr>
236: * <td width="20%"><code>TypeDeclaration</code></td>
237: * <td width="50%"><code>modifiers, isInterface, name, superclass,
238: * superInterfaces, typeParameters<br>
239: * RELATIVE_ORDER property</code></td>
240: * </tr>
241: * <tr>
242: * <td width="20%"><code>FieldDeclaration</code></td>
243: * <td width="50%"><code>modifiers, type, fragments
244: * (VariableDeclarationFragments
245: * with name only)<br>
246: * RELATIVE_ORDER property</code></td>
247: * </tr>
248: * <tr>
249: * <td width="20%"><code>MethodDeclaration</code></td>
250: * <td width="50%"><code>modifiers, isConstructor, returnType, name,
251: * typeParameters, parameters
252: * (SingleVariableDeclarations with name, type, and modifiers only),
253: * thrownExceptions<br>
254: * RELATIVE_ORDER property</code></td>
255: * </tr>
256: * <tr>
257: * <td width="20%"><code>Initializer</code></td>
258: * <td width="50%"><code>modifiers<br>
259: * RELATIVE_ORDER property</code></td>
260: * </tr>
261: * <tr>
262: * <td width="20%"><code>AnnotationTypeDeclaration</code></td>
263: * <td width="50%"><code>modifiers, name<br>
264: * RELATIVE_ORDER property</code></td>
265: * </tr>
266: * <tr>
267: * <td width="20%"><code>AnnotationTypeMemberDeclaration</code></td>
268: * <td width="50%"><code>modifiers, name, type, default<br>
269: * RELATIVE_ORDER property</code></td>
270: * </tr>
271: * <tr>
272: * <td width="20%"><code>EnumDeclaration</code></td>
273: * <td width="50%"><code>modifiers, name, superInterfaces<br>
274: * RELATIVE_ORDER property</code></td>
275: * </tr>
276: * <tr>
277: * <td width="20%"><code>EnumConstantDeclaration</code></td>
278: * <td width="50%"><code>modifiers, name, arguments<br>
279: * RELATIVE_ORDER property</code></td>
280: * </tr>
281: * </table>
282: * Clients should not rely on the AST nodes being properly parented or on
283: * having source range information. (Future releases may provide options
284: * for requesting additional information like source positions, full ASTs,
285: * non-recursive sorting, etc.)
286: * </p>
287: *
288: * @param level the AST level; one of the AST LEVEL constants
289: * @param compilationUnit the given compilation unit, which must be a
290: * working copy
291: * @param positions an array of source positions to map, or
292: * <code>null</code> if none. If supplied, the positions must
293: * character-based source positions within the original source code for
294: * the given compilation unit, arranged in non-decreasing order.
295: * The array is updated in place when this method returns to reflect the
296: * corresponding source positions in the permuted source code string
297: * (but not necessarily any longer in non-decreasing order).
298: * @param comparator the comparator capable of ordering
299: * <code>BodyDeclaration</code>s; this comparator is passed AST nodes
300: * from an AST of the specified AST level
301: * @param options bitwise-or of option flags; <code>0</code> for default
302: * behavior (reserved for future growth)
303: * @param monitor the progress monitor to notify, or <code>null</code> if
304: * none
305: * @exception JavaModelException if the compilation unit could not be
306: * sorted. Reasons include:
307: * <ul>
308: * <li> The given compilation unit does not exist (ELEMENT_DOES_NOT_EXIST)</li>
309: * <li> The given compilation unit is not a working copy (INVALID_ELEMENT_TYPES)</li>
310: * <li> A <code>CoreException</code> occurred while accessing the underlying
311: * resource
312: * </ul>
313: * @exception IllegalArgumentException if the given compilation unit is null
314: * or if the given comparator is null, or if <code>level</code> is not one of
315: * the AST JLS level constants.
316: * @see org.eclipse.jdt.core.dom.BodyDeclaration
317: * @see #RELATIVE_ORDER
318: * @since 3.1
319: */
320: public static void sort(int level,
321: ICompilationUnit compilationUnit, int[] positions,
322: Comparator comparator, int options, IProgressMonitor monitor)
323: throws JavaModelException {
324: if (compilationUnit == null || comparator == null) {
325: throw new IllegalArgumentException();
326: }
327: checkASTLevel(level);
328: ICompilationUnit[] compilationUnits = new ICompilationUnit[] { compilationUnit };
329: SortElementsOperation operation = new SortElementsOperation(
330: level, compilationUnits, positions, comparator);
331: operation.runOperation(monitor);
332: }
333:
334: /**
335: * Reorders the declarations in the given compilation unit according to the
336: * specified comparator. The caller is responsible for arranging in advance
337: * that the given compilation unit is a working copy, and for applying the
338: * returned TextEdit afterwards.
339: * <p>
340: * <b>Note:</b> Reordering the members within a type declaration might be
341: * more than a cosmetic change and could have potentially serious
342: * repercussions. Firstly, the order in which the fields of a type are
343: * initialized is significant in the Java language; reordering fields and
344: * initializers may result in compilation errors or change the execution
345: * behavior of the code. Secondly, reordering a class's members may affect
346: * how its instances are serialized. This operation should therefore be used
347: * with caution and due concern for potential negative side effects.
348: * </p>
349: * <p>
350: * The <code>compare</code> method of the given comparator is passed pairs
351: * of body declarations (subclasses of <code>BodyDeclaration</code>)
352: * representing body declarations at the same level.
353: * The comparator is called on body declarations of nested classes,
354: * including anonymous and local classes, but always at the same level.
355: * Clients need to provide a comparator implementation (there is no standard
356: * comparator). The <code>RELATIVE_ORDER</code> property attached to these
357: * AST nodes affords the comparator a way to preserve the original relative
358: * order.
359: * </p>
360: * <p>
361: * The body declarations passed as parameters to the comparator always carry
362: * at least the following minimal signature information: <br>
363: * <table border="1" width="80%" cellpadding="5">
364: * <tr>
365: * <td width="20%"><code>TypeDeclaration</code></td>
366: * <td width="50%"><code>modifiers, isInterface, name, superclass,
367: * superInterfaces, typeParameters<br>
368: * RELATIVE_ORDER property</code></td>
369: * </tr>
370: * <tr>
371: * <td width="20%"><code>FieldDeclaration</code></td>
372: * <td width="50%"><code>modifiers, type, fragments
373: * (VariableDeclarationFragments
374: * with name only)<br>
375: * RELATIVE_ORDER property</code></td>
376: * </tr>
377: * <tr>
378: * <td width="20%"><code>MethodDeclaration</code></td>
379: * <td width="50%"><code>modifiers, isConstructor, returnType, name,
380: * typeParameters, parameters
381: * (SingleVariableDeclarations with name, type, and modifiers only),
382: * thrownExceptions<br>
383: * RELATIVE_ORDER property</code></td>
384: * </tr>
385: * <tr>
386: * <td width="20%"><code>Initializer</code></td>
387: * <td width="50%"><code>modifiers<br>
388: * RELATIVE_ORDER property</code></td>
389: * </tr>
390: * <tr>
391: * <td width="20%"><code>AnnotationTypeDeclaration</code></td>
392: * <td width="50%"><code>modifiers, name<br>
393: * RELATIVE_ORDER property</code></td>
394: * </tr>
395: * <tr>
396: * <td width="20%"><code>AnnotationTypeMemberDeclaration</code></td>
397: * <td width="50%"><code>modifiers, name, type, default<br>
398: * RELATIVE_ORDER property</code></td>
399: * </tr>
400: * <tr>
401: * <td width="20%"><code>EnumDeclaration</code></td>
402: * <td width="50%"><code>modifiers, name, superInterfaces<br>
403: * RELATIVE_ORDER property</code></td>
404: * </tr>
405: * <tr>
406: * <td width="20%"><code>EnumConstantDeclaration</code></td>
407: * <td width="50%"><code>modifiers, name, arguments<br>
408: * RELATIVE_ORDER property</code></td>
409: * </tr>
410: * </table>
411: * </p>
412: *
413: * @param unit
414: * the CompilationUnit to sort
415: * @param comparator
416: * the comparator capable of ordering
417: * <code>BodyDeclaration</code>s; this comparator is passed
418: * AST nodes from an AST of the specified AST level
419: * @param options
420: * bitwise-or of option flags; <code>0</code> for default
421: * behavior (reserved for future growth)
422: * @param group
423: * the text edit group to use when generating text edits, or <code>null</code>
424: * @param monitor
425: * the progress monitor to notify, or <code>null</code> if none
426: * @return a TextEdit describing the required edits to do the sort, or <code>null</code>
427: * if sorting is not required
428: * @exception JavaModelException
429: * if the compilation unit could not be sorted. Reasons
430: * include:
431: * <ul>
432: * <li> The given unit was not created from a ICompilationUnit (INVALID_ELEMENT_TYPES)</li>
433: * </ul>
434: * @exception IllegalArgumentException
435: * if the given compilation unit is null or if the given
436: * comparator is null, or if <code>options</code> is not one
437: * of the supported levels.
438: * @see org.eclipse.jdt.core.dom.BodyDeclaration
439: * @see #RELATIVE_ORDER
440: * @since 3.3
441: */
442: public static TextEdit sort(CompilationUnit unit,
443: Comparator comparator, int options, TextEditGroup group,
444: IProgressMonitor monitor) throws JavaModelException {
445: if (unit == null || comparator == null) {
446: throw new IllegalArgumentException();
447: }
448: SortElementsOperation operation = new SortElementsOperation(
449: AST.JLS3, new IJavaElement[] { unit.getJavaElement() },
450: null, comparator);
451: return operation.calculateEdit(unit, group);
452: }
453: }
|