/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Alex Blewitt - alex_blewitt@yahoo.com https://bugs.eclipse.org/bugs/show_bug.cgi?id=171066 *******************************************************************************/ package org.eclipse.jdt.core.util; import java.util.Comparator; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.internal.core.SortElementsOperation; import org.eclipse.text.edits.TextEdit; import org.eclipse.text.edits.TextEditGroup; /** * Operation for sorting members within a compilation unit. * <p> * This class provides all functionality via static members. * </p> * * @since 2.1 * @noinstantiate This class is not intended to be instantiated by clients. */ @SuppressWarnings("rawtypes") public final class CompilationUnitSorter { /** * Private constructor to prevent instantiation. */ private CompilationUnitSorter() { // Not instantiable } /** * @deprecated marking deprecated as it is using deprecated code */ private static void checkASTLevel(int level) { switch (level) { case AST.JLS2 : case AST.JLS3 : case AST.JLS4 : case AST.JLS8 : break; default : throw new IllegalArgumentException(); } } /** * Name of auxillary property whose value can be used to determine the * original relative order of two body declarations. This allows a * comparator to preserve the relative positions of certain kinds of * body declarations when required. * <p> * All body declarations passed to the comparator's <code>compare</code> * method by <code>CompilationUnitSorter.sort</code> carry an * Integer-valued property. The body declaration with the lower value * comes before the one with the higher value. The exact numeric value * of these properties is unspecified. * </p> * <p> * Example usage: * <pre> * BodyDeclaration b1 = (BodyDeclaration) object1; * BodyDeclaration b2 = (BodyDeclaration) object2; * Integer i1 = (Integer) b1.getProperty(RELATIVE_ORDER); * Integer i2 = (Integer) b2.getProperty(RELATIVE_ORDER); * return i1.intValue() - i2.intValue(); // preserve original order * </pre> * </p> * * @see #sort(ICompilationUnit, int[], Comparator, int, IProgressMonitor) * @see org.eclipse.jdt.core.dom.BodyDeclaration */ public static final String RELATIVE_ORDER = "relativeOrder"; //$NON-NLS-1$ /** * Reorders the declarations in the given compilation unit according to * JLS2 rules. The caller is * responsible for arranging in advance that the given compilation unit is * a working copy, and for saving the changes afterwards. * <p> * <b>Note:</b> Reordering the members within a type declaration might be * more than a cosmetic change and could have potentially serious * repercussions. Firstly, the order in which the fields of a type are * initialized is significant in the Java language; reordering fields * and initializers may result in compilation errors or change the execution * behavior of the code. Secondly, reordering a class's members may affect * how its instances are serialized. This operation should therefore be used * with caution and due concern for potential negative side effects. * </p> * <p> * The optional <code>positions</code> array contains a non-decreasing * ordered list of character-based source positions within the compilation * unit's source code string. Upon return from this method, the positions in * the array reflect the corresponding new locations in the modified source * code string. Note that this operation modifies the given array in place. * </p> * <p> * The <code>compare</code> method of the given comparator is passed pairs * of JLS2 AST body declarations (subclasses of <code>BodyDeclaration</code>) * representing body declarations at the same level. The comparator is * called on body declarations of nested classes, including anonymous and * local classes, but always at the same level. Clients need to provide * a comparator implementation (there is no standard comparator). The * <code>RELATIVE_ORDER</code> property attached to these AST nodes afforts * the comparator a way to preserve the original relative order. * </p> * <p> * The body declarations passed as parameters to the comparator * always carry at least the following minimal signature information: * <br> * <table border="1" width="80%" cellpadding="5"> * <tr> * <td width="20%"><code>TypeDeclaration</code></td> * <td width="50%"><code>modifiers, isInterface, name, superclass, * superInterfaces<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>FieldDeclaration</code></td> * <td width="50%"><code>modifiers, type, fragments * (VariableDeclarationFragments * with name only)<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>MethodDeclaration</code></td> * <td width="50%"><code>modifiers, isConstructor, returnType, name, * parameters * (SingleVariableDeclarations with name and type only), * thrownExceptions<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>Initializer</code></td> * <td width="50%"><code>modifiers<br> * RELATIVE_ORDER property</code></td> * </tr> * </table> * Clients should not rely on the AST nodes being properly parented or on * having source range information. (Future releases may provide options * for requesting additional information like source positions, full ASTs, * non-recursive sorting, etc.) * </p> * * @param compilationUnit the given compilation unit, which must be a * working copy * @param positions an array of source positions to map, or * <code>null</code> if none. If supplied, the positions must * character-based source positions within the original source code for * the given compilation unit, arranged in non-decreasing order. * The array is updated in place when this method returns to reflect the * corresponding source positions in the permuted source code string * (but not necessarily any longer in non-decreasing order). * @param comparator the comparator capable of ordering * <code>BodyDeclaration</code>s; this comparator is passed AST nodes * from a JLS2 AST * @param options bitwise-or of option flags; <code>0</code> for default * behavior (reserved for future growth) * @param monitor the progress monitor to notify, or <code>null</code> if * none * @exception JavaModelException if the compilation unit could not be * sorted. Reasons include: * <ul> * <li> The given compilation unit does not exist (ELEMENT_DOES_NOT_EXIST)</li> * <li> The given compilation unit is not a working copy (INVALID_ELEMENT_TYPES)</li> * <li> A <code>CoreException</code> occurred while accessing the underlying * resource * </ul> * @exception IllegalArgumentException if the given compilation unit is null * or if the given comparator is null. * @see org.eclipse.jdt.core.dom.BodyDeclaration * @see #RELATIVE_ORDER * @deprecated Clients should port their code to use the new JLS3 AST API and call * {@link #sort(int, ICompilationUnit, int[], Comparator, int, IProgressMonitor) * CompilationUnitSorter.sort(AST.JLS3, compilationUnit, positions, comparator, options, monitor)} * instead of using this method. */ public static void sort(ICompilationUnit compilationUnit, int[] positions, Comparator comparator, int options, IProgressMonitor monitor) throws JavaModelException { sort(AST.JLS2, compilationUnit, positions, comparator, options, monitor); } /** * Reorders the declarations in the given compilation unit according to * the specified AST level. The caller is responsible for arranging in * advance that the given compilation unit is a working copy, and for * saving the changes afterwards. * <p> * <b>Note:</b> Reordering the members within a type declaration might be * more than a cosmetic change and could have potentially serious * repercussions. Firstly, the order in which the fields of a type are * initialized is significant in the Java language; reordering fields * and initializers may result in compilation errors or change the execution * behavior of the code. Secondly, reordering a class's members may affect * how its instances are serialized. This operation should therefore be used * with caution and due concern for potential negative side effects. * </p> * <p> * The optional <code>positions</code> array contains a non-decreasing * ordered list of character-based source positions within the compilation * unit's source code string. Upon return from this method, the positions in * the array reflect the corresponding new locations in the modified source * code string. Note that this operation modifies the given array in place. * </p> * <p> * The <code>compare</code> method of the given comparator is passed pairs * of body declarations (subclasses of <code>BodyDeclaration</code>) * representing body declarations at the same level. The nodes are from an * AST of the specified level * ({@link org.eclipse.jdt.core.dom.ASTParser#newParser(int)}. Clients * will generally specify the latest available <code>{@link AST}.JLS*</code> constant since that will * cover all constructs found in all version of Java source code. * The comparator is called on body declarations of nested classes, including * anonymous and local classes, but always at the same level. Clients need to provide * a comparator implementation (there is no standard comparator). The * <code>RELATIVE_ORDER</code> property attached to these AST nodes afforts * the comparator a way to preserve the original relative order. * </p> * <p> * The body declarations passed as parameters to the comparator * always carry at least the following minimal signature information: * <br> * <table border="1" width="80%" cellpadding="5"> * <tr> * <td width="20%"><code>TypeDeclaration</code></td> * <td width="50%"><code>modifiers, isInterface, name, superclass, * superInterfaces, typeParameters<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>FieldDeclaration</code></td> * <td width="50%"><code>modifiers, type, fragments * (VariableDeclarationFragments * with name only)<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>MethodDeclaration</code></td> * <td width="50%"><code>modifiers, isConstructor, returnType, name, * typeParameters, parameters * (SingleVariableDeclarations with name, type, and modifiers only), * thrownExceptions<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>Initializer</code></td> * <td width="50%"><code>modifiers<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>AnnotationTypeDeclaration</code></td> * <td width="50%"><code>modifiers, name<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>AnnotationTypeMemberDeclaration</code></td> * <td width="50%"><code>modifiers, name, type, default<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>EnumDeclaration</code></td> * <td width="50%"><code>modifiers, name, superInterfaces<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>EnumConstantDeclaration</code></td> * <td width="50%"><code>modifiers, name, arguments<br> * RELATIVE_ORDER property</code></td> * </tr> * </table> * Clients should not rely on the AST nodes being properly parented or on * having source range information. (Future releases may provide options * for requesting additional information like source positions, full ASTs, * non-recursive sorting, etc.) * </p> * * @param level the AST level; one of the <code>{@link AST}.JLS*</code> constants * @param compilationUnit the given compilation unit, which must be a * working copy * @param positions an array of source positions to map, or * <code>null</code> if none. If supplied, the positions must * character-based source positions within the original source code for * the given compilation unit, arranged in non-decreasing order. * The array is updated in place when this method returns to reflect the * corresponding source positions in the permuted source code string * (but not necessarily any longer in non-decreasing order). * @param comparator the comparator capable of ordering * <code>BodyDeclaration</code>s; this comparator is passed AST nodes * from an AST of the specified AST level * @param options bitwise-or of option flags; <code>0</code> for default * behavior (reserved for future growth) * @param monitor the progress monitor to notify, or <code>null</code> if * none * @exception JavaModelException if the compilation unit could not be * sorted. Reasons include: * <ul> * <li> The given compilation unit does not exist (ELEMENT_DOES_NOT_EXIST)</li> * <li> The given compilation unit is not a working copy (INVALID_ELEMENT_TYPES)</li> * <li> A <code>CoreException</code> occurred while accessing the underlying * resource * </ul> * @exception IllegalArgumentException if the given compilation unit is null * or if the given comparator is null, or if <code>level</code> is not one of * the AST JLS level constants. * @see org.eclipse.jdt.core.dom.BodyDeclaration * @see #RELATIVE_ORDER * @since 3.1 */ public static void sort(int level, ICompilationUnit compilationUnit, int[] positions, Comparator comparator, int options, IProgressMonitor monitor) throws JavaModelException { if (compilationUnit == null || comparator == null) { throw new IllegalArgumentException(); } checkASTLevel(level); ICompilationUnit[] compilationUnits = new ICompilationUnit[] { compilationUnit }; SortElementsOperation operation = new SortElementsOperation(level, compilationUnits, positions, comparator); operation.runOperation(monitor); } /** * Reorders the declarations in the given compilation unit according to the * specified comparator. The caller is responsible for arranging in advance * that the given compilation unit is a working copy, and for applying the * returned TextEdit afterwards. * <p> * <b>Note:</b> Reordering the members within a type declaration might be * more than a cosmetic change and could have potentially serious * repercussions. Firstly, the order in which the fields of a type are * initialized is significant in the Java language; reordering fields and * initializers may result in compilation errors or change the execution * behavior of the code. Secondly, reordering a class's members may affect * how its instances are serialized. This operation should therefore be used * with caution and due concern for potential negative side effects. * </p> * <p> * The <code>compare</code> method of the given comparator is passed pairs * of body declarations (subclasses of <code>BodyDeclaration</code>) * representing body declarations at the same level. * The comparator is called on body declarations of nested classes, * including anonymous and local classes, but always at the same level. * Clients need to provide a comparator implementation (there is no standard * comparator). The <code>RELATIVE_ORDER</code> property attached to these * AST nodes affords the comparator a way to preserve the original relative * order. * </p> * <p> * The body declarations passed as parameters to the comparator always carry * at least the following minimal signature information: <br> * <table border="1" width="80%" cellpadding="5"> * <tr> * <td width="20%"><code>TypeDeclaration</code></td> * <td width="50%"><code>modifiers, isInterface, name, superclass, * superInterfaces, typeParameters<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>FieldDeclaration</code></td> * <td width="50%"><code>modifiers, type, fragments * (VariableDeclarationFragments * with name only)<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>MethodDeclaration</code></td> * <td width="50%"><code>modifiers, isConstructor, returnType, name, * typeParameters, parameters * (SingleVariableDeclarations with name, type, and modifiers only), * thrownExceptions<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>Initializer</code></td> * <td width="50%"><code>modifiers<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>AnnotationTypeDeclaration</code></td> * <td width="50%"><code>modifiers, name<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>AnnotationTypeMemberDeclaration</code></td> * <td width="50%"><code>modifiers, name, type, default<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>EnumDeclaration</code></td> * <td width="50%"><code>modifiers, name, superInterfaces<br> * RELATIVE_ORDER property</code></td> * </tr> * <tr> * <td width="20%"><code>EnumConstantDeclaration</code></td> * <td width="50%"><code>modifiers, name, arguments<br> * RELATIVE_ORDER property</code></td> * </tr> * </table> * </p> * * @param unit * the CompilationUnit to sort * @param comparator * the comparator capable of ordering * <code>BodyDeclaration</code>s; this comparator is passed * AST nodes from an AST of the specified AST level * @param options * bitwise-or of option flags; <code>0</code> for default * behavior (reserved for future growth) * @param group * the text edit group to use when generating text edits, or <code>null</code> * @param monitor * the progress monitor to notify, or <code>null</code> if none * @return a TextEdit describing the required edits to do the sort, or <code>null</code> * if sorting is not required * @exception JavaModelException * if the compilation unit could not be sorted. Reasons * include: * <ul> * <li> The given unit was not created from a ICompilationUnit (INVALID_ELEMENT_TYPES)</li> * </ul> * @exception IllegalArgumentException * if the given compilation unit is null or if the given * comparator is null, or if <code>options</code> is not one * of the supported levels. * @see org.eclipse.jdt.core.dom.BodyDeclaration * @see #RELATIVE_ORDER * @since 3.3 */ public static TextEdit sort(CompilationUnit unit, Comparator comparator, int options, TextEditGroup group, IProgressMonitor monitor) throws JavaModelException { if (unit == null || comparator == null) { throw new IllegalArgumentException(); } SortElementsOperation operation = new SortElementsOperation(unit.getAST().apiLevel(), new IJavaElement[] { unit.getJavaElement() }, null, comparator); return operation.calculateEdit(unit, group); } }