]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-after/core extension/org/eclipse/jdt/internal/corext/util/MethodsSourcePositionComparator.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core extension / org / eclipse / jdt / internal / corext / util / MethodsSourcePositionComparator.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2009, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Mateusz Wenus <mateusz.wenus@gmail.com> - [override method] generate in declaration order [code generation] - https://bugs.eclipse.org/bugs/show_bug.cgi?id=140971
10 * IBM Corporation - bug fixes
11 *******************************************************************************/
12package org.eclipse.jdt.internal.corext.util;
13
14import java.util.Comparator;
15
16import org.eclipse.jdt.core.IMethod;
17import org.eclipse.jdt.core.ISourceRange;
18import org.eclipse.jdt.core.JavaModelException;
19import org.eclipse.jdt.core.SourceRange;
20import org.eclipse.jdt.core.dom.IMethodBinding;
21import org.eclipse.jdt.core.dom.ITypeBinding;
22
23/**
24 * A comparator which sorts methods (IMethodBinding) of a type passed as constructor argument,
25 * according to their order in source files. More formally, if <code>m1</code> and <code>m2</code>
26 * are methods of type <code>T</code> then according to this comparator <code>m1</code> is less than
27 * <code>m2</code> iff one of following holds:
28 * <ul>
29 * <li><code>m1</code> and <code>m2</code> are defined in the same type (<code>T</code> or any
30 * supertype of <code>T</code>), that type has a source attachment and <code>m1</code> appears
31 * before <code>m2</code> in source of that type</li>
32 * <li><code>m1</code> and <code>m2</code> are defined in the same type (<code>T</code> or any
33 * supertype of <code>T</code>), that type doesn't have a source attachment and name of
34 * <code>m1</code> alphabetically precedes name of <code>m2</code></li>
35 *
36 * <li><code>m2</code> is defined in <code>T</code> and <code>m1</code> is defined in any supertype
37 * of <code>T</code></li>
38 * <li><code>m2</code> is defined in a superclass of <code>T</code> and <code>m1</code> is defined
39 * in a superinterface of <code>T</code></li>
40 * <li><code>m1</code> and <code>m2</code> are defined in different superclasses of <code>T</code>
41 * and a class which defines <code>m1</code> extends class which defines <code>m2</code>
42 * <li><code>m1</code> and <code>m2</code> are defined in different superinterfaces of
43 * <code>T</code> and an interface which defines <code>m2</code> appears before an interface which
44 * defines <code>m1</code> in <code>implements</code> clause of declaration of type <code>T</code></li>
45 * </ul>
46 */
47public class MethodsSourcePositionComparator implements Comparator<IMethodBinding> {
48
49 private final ITypeBinding fTypeBinding;
50
51 public MethodsSourcePositionComparator(ITypeBinding typeBinding) {
52 if (typeBinding == null) {
53 throw new IllegalArgumentException();
54 }
55 fTypeBinding= typeBinding;
56 }
57
58 public int compare(IMethodBinding firstMethodBinding, IMethodBinding secondMethodBinding) {
59 if (firstMethodBinding == null || secondMethodBinding == null) {
60 return 0;
61 }
62 ITypeBinding firstMethodType= firstMethodBinding.getDeclaringClass();
63 ITypeBinding secondMethodType= secondMethodBinding.getDeclaringClass();
64
65 if (firstMethodType.equals(secondMethodType)) {
66 return compareInTheSameType(firstMethodBinding, secondMethodBinding);
67 }
68
69 if (firstMethodType.equals(fTypeBinding)) {
70 return 1;
71 }
72 if (secondMethodType.equals(fTypeBinding)) {
73 return -1;
74 }
75
76 ITypeBinding type= fTypeBinding;
77 int count= 0, firstCount= -1, secondCount= -1;
78 while ((type= type.getSuperclass()) != null) {
79 if (firstMethodType.equals(type)) {
80 firstCount= count;
81 }
82 if (secondMethodType.equals(type)) {
83 secondCount= count;
84 }
85 count++;
86 }
87 if (firstCount != -1 && secondCount != -1) {
88 return (firstCount - secondCount);
89 }
90 if (firstCount != -1 && secondCount == -1) {
91 return 1;
92 }
93 if (firstCount == -1 && secondCount != -1) {
94 return -1;
95 }
96
97 ITypeBinding[] interfaces= fTypeBinding.getInterfaces();
98 for (int i= 0; i < interfaces.length; i++) {
99 if (firstMethodType.equals(interfaces[i])) {
100 return 1;
101 }
102 if (secondMethodType.equals(interfaces[i])) {
103 return -1;
104 }
105 }
106 return 0;
107 }
108
109 private int compareInTheSameType(IMethodBinding firstMethodBinding, IMethodBinding secondMethodBinding) {
110 try {
111 IMethod firstMethod= (IMethod)firstMethodBinding.getJavaElement();
112 IMethod secondMethod= (IMethod)secondMethodBinding.getJavaElement();
113 if (firstMethod == null || secondMethod == null) {
114 return 0;
115 }
116 ISourceRange firstSourceRange= firstMethod.getSourceRange();
117 ISourceRange secondSourceRange= secondMethod.getSourceRange();
118
119 if (!SourceRange.isAvailable(firstSourceRange) || !SourceRange.isAvailable(secondSourceRange)) {
120 return firstMethod.getElementName().compareTo(secondMethod.getElementName());
121 } else {
122 return firstSourceRange.getOffset() - secondSourceRange.getOffset();
123 }
124 } catch (JavaModelException e) {
125 return 0;
126 }
127 }
128}