Copyright (c) 2009, 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/ SPDX-License-Identifier: EPL-2.0 Contributors: Mateusz Wenus - [override method] generate in declaration order [code generation] - https://bugs.eclipse.org/bugs/show_bug.cgi?id=140971 IBM Corporation - bug fixes Red Hat Inc. - refactored to jdt.core.manipulation
/******************************************************************************* * Copyright (c) 2009, 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/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * Mateusz Wenus <mateusz.wenus@gmail.com> - [override method] generate in declaration order [code generation] - https://bugs.eclipse.org/bugs/show_bug.cgi?id=140971 * IBM Corporation - bug fixes * Red Hat Inc. - refactored to jdt.core.manipulation *******************************************************************************/
package org.eclipse.jdt.internal.corext.util; import java.util.Comparator; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.SourceRange; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding;
A comparator which sorts methods (IMethodBinding) of a type passed as constructor argument, according to their order in source files. More formally, if m1 and m2 are methods of type T then according to this comparator m1 is less than m2 iff one of following holds:
  • m1 and m2 are defined in the same type (T or any supertype of T), that type has a source attachment and m1 appears before m2 in source of that type
  • m1 and m2 are defined in the same type (T or any supertype of T), that type doesn't have a source attachment and name of m1 alphabetically precedes name of m2
  • m2 is defined in T and m1 is defined in any supertype of T
  • m2 is defined in a superclass of T and m1 is defined in a superinterface of T
  • m1 and m2 are defined in different superclasses of T and a class which defines m1 extends class which defines m2
  • m1 and m2 are defined in different superinterfaces of T and an interface which defines m2 appears before an interface which defines m1 in implements clause of declaration of type T
/** * A comparator which sorts methods (IMethodBinding) of a type passed as constructor argument, * according to their order in source files. More formally, if <code>m1</code> and <code>m2</code> * are methods of type <code>T</code> then according to this comparator <code>m1</code> is less than * <code>m2</code> iff one of following holds: * <ul> * <li><code>m1</code> and <code>m2</code> are defined in the same type (<code>T</code> or any * supertype of <code>T</code>), that type has a source attachment and <code>m1</code> appears * before <code>m2</code> in source of that type</li> * <li><code>m1</code> and <code>m2</code> are defined in the same type (<code>T</code> or any * supertype of <code>T</code>), that type doesn't have a source attachment and name of * <code>m1</code> alphabetically precedes name of <code>m2</code></li> * * <li><code>m2</code> is defined in <code>T</code> and <code>m1</code> is defined in any supertype * of <code>T</code></li> * <li><code>m2</code> is defined in a superclass of <code>T</code> and <code>m1</code> is defined * in a superinterface of <code>T</code></li> * <li><code>m1</code> and <code>m2</code> are defined in different superclasses of <code>T</code> * and a class which defines <code>m1</code> extends class which defines <code>m2</code> * <li><code>m1</code> and <code>m2</code> are defined in different superinterfaces of * <code>T</code> and an interface which defines <code>m2</code> appears before an interface which * defines <code>m1</code> in <code>implements</code> clause of declaration of type <code>T</code></li> * </ul> */
public class MethodsSourcePositionComparator implements Comparator<IMethodBinding> { private final ITypeBinding fTypeBinding; public MethodsSourcePositionComparator(ITypeBinding typeBinding) { if (typeBinding == null) { throw new IllegalArgumentException(); } fTypeBinding= typeBinding; } @Override public int compare(IMethodBinding firstMethodBinding, IMethodBinding secondMethodBinding) { if (firstMethodBinding == null || secondMethodBinding == null) { return 0; } ITypeBinding firstMethodType= firstMethodBinding.getDeclaringClass(); ITypeBinding secondMethodType= secondMethodBinding.getDeclaringClass(); if (firstMethodType.equals(secondMethodType)) { return compareInTheSameType(firstMethodBinding, secondMethodBinding); } if (firstMethodType.equals(fTypeBinding)) { return 1; } if (secondMethodType.equals(fTypeBinding)) { return -1; } ITypeBinding type= fTypeBinding; int count= 0, firstCount= -1, secondCount= -1; while ((type= type.getSuperclass()) != null) { if (firstMethodType.equals(type)) { firstCount= count; } if (secondMethodType.equals(type)) { secondCount= count; } count++; } if (firstCount != -1 && secondCount != -1) { return (firstCount - secondCount); } if (firstCount != -1 && secondCount == -1) { return 1; } if (firstCount == -1 && secondCount != -1) { return -1; } ITypeBinding[] interfaces= fTypeBinding.getInterfaces(); for (int i= 0; i < interfaces.length; i++) { if (firstMethodType.equals(interfaces[i])) { return 1; } if (secondMethodType.equals(interfaces[i])) { return -1; } } return 0; } private int compareInTheSameType(IMethodBinding firstMethodBinding, IMethodBinding secondMethodBinding) { try { IMethod firstMethod= (IMethod)firstMethodBinding.getJavaElement(); IMethod secondMethod= (IMethod)secondMethodBinding.getJavaElement(); if (firstMethod == null || secondMethod == null) { return 0; } ISourceRange firstSourceRange= firstMethod.getSourceRange(); ISourceRange secondSourceRange= secondMethod.getSourceRange(); if (!SourceRange.isAvailable(firstSourceRange) || !SourceRange.isAvailable(secondSourceRange)) { return firstMethod.getElementName().compareTo(secondMethod.getElementName()); } else { return firstSourceRange.getOffset() - secondSourceRange.getOffset(); } } catch (JavaModelException e) { return 0; } } }