/plug-ins/helios/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingComparator.java

https://github.com/vazexqi/CodingSpectator · Java · 313 lines · 251 code · 21 blank · 41 comment · 111 complexity · f76f06adb75a3ccd18a1845fb1060599 MD5 · raw file

  1. /*******************************************************************************
  2. * Copyright (c) 2004, 2008 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. * IBM Corporation - initial API and implementation
  10. *******************************************************************************/
  11. package org.eclipse.jdt.core.dom;
  12. import java.util.HashSet;
  13. import org.eclipse.jdt.core.compiler.CharOperation;
  14. import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
  15. import org.eclipse.jdt.internal.compiler.lookup.Binding;
  16. import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
  17. import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
  18. import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
  19. import org.eclipse.jdt.internal.compiler.lookup.ImportBinding;
  20. import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
  21. import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
  22. import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
  23. import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
  24. import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
  25. /**
  26. * Internal helper class for comparing bindings.
  27. *
  28. * @since 3.1
  29. */
  30. class BindingComparator {
  31. /**
  32. * @param bindings
  33. * @param otherBindings
  34. * @return true if both parameters are equals, false otherwise
  35. */
  36. static boolean isEqual(TypeVariableBinding[] bindings, TypeVariableBinding[] otherBindings) {
  37. if (bindings == null) {
  38. return otherBindings == null;
  39. }
  40. if (otherBindings == null) {
  41. return false;
  42. }
  43. int length= bindings.length;
  44. int otherLength= otherBindings.length;
  45. if (length != otherLength) {
  46. return false;
  47. }
  48. for (int i= 0; i < length; i++) {
  49. TypeVariableBinding typeVariableBinding= bindings[i];
  50. TypeVariableBinding typeVariableBinding2= otherBindings[i];
  51. if (!isEqual(typeVariableBinding, typeVariableBinding2)) {
  52. return false;
  53. }
  54. }
  55. return true;
  56. }
  57. /**
  58. * @param declaringElement
  59. * @param declaringElement2
  60. * @return true if both parameters are equals, false otherwise
  61. */
  62. static boolean isEqual(Binding declaringElement, Binding declaringElement2, HashSet visitedTypes) {
  63. if (declaringElement instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
  64. if (!(declaringElement2 instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding)) {
  65. return false;
  66. }
  67. return isEqual((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)declaringElement,
  68. (org.eclipse.jdt.internal.compiler.lookup.TypeBinding)declaringElement2,
  69. visitedTypes);
  70. } else if (declaringElement instanceof org.eclipse.jdt.internal.compiler.lookup.MethodBinding) {
  71. if (!(declaringElement2 instanceof org.eclipse.jdt.internal.compiler.lookup.MethodBinding)) {
  72. return false;
  73. }
  74. return isEqual((org.eclipse.jdt.internal.compiler.lookup.MethodBinding)declaringElement,
  75. (org.eclipse.jdt.internal.compiler.lookup.MethodBinding)declaringElement2,
  76. visitedTypes);
  77. } else if (declaringElement instanceof VariableBinding) {
  78. if (!(declaringElement2 instanceof VariableBinding)) {
  79. return false;
  80. }
  81. return isEqual((VariableBinding)declaringElement,
  82. (VariableBinding)declaringElement2);
  83. } else if (declaringElement instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding) {
  84. if (!(declaringElement2 instanceof org.eclipse.jdt.internal.compiler.lookup.PackageBinding)) {
  85. return false;
  86. }
  87. org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding= (org.eclipse.jdt.internal.compiler.lookup.PackageBinding)declaringElement;
  88. org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding2= (org.eclipse.jdt.internal.compiler.lookup.PackageBinding)declaringElement2;
  89. return CharOperation.equals(packageBinding.compoundName, packageBinding2.compoundName);
  90. } else if (declaringElement instanceof ImportBinding) {
  91. if (!(declaringElement2 instanceof ImportBinding)) {
  92. return false;
  93. }
  94. ImportBinding importBinding= (ImportBinding)declaringElement;
  95. ImportBinding importBinding2= (ImportBinding)declaringElement2;
  96. return importBinding.isStatic() == importBinding2.isStatic()
  97. && importBinding.onDemand == importBinding2.onDemand
  98. && CharOperation.equals(importBinding.compoundName, importBinding2.compoundName);
  99. }
  100. return false;
  101. }
  102. static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding,
  103. org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding2) {
  104. return isEqual(methodBinding, methodBinding2, new HashSet());
  105. }
  106. static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding,
  107. org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding2,
  108. HashSet visitedTypes) {
  109. if (methodBinding == null) {
  110. return methodBinding2 == null;
  111. }
  112. if (methodBinding2 == null)
  113. return false;
  114. return CharOperation.equals(methodBinding.selector, methodBinding2.selector)
  115. && isEqual(methodBinding.returnType, methodBinding2.returnType, visitedTypes)
  116. && isEqual(methodBinding.thrownExceptions, methodBinding2.thrownExceptions, visitedTypes)
  117. && isEqual(methodBinding.declaringClass, methodBinding2.declaringClass, visitedTypes)
  118. && isEqual(methodBinding.typeVariables, methodBinding2.typeVariables, visitedTypes)
  119. && isEqual(methodBinding.parameters, methodBinding2.parameters, visitedTypes);
  120. }
  121. static boolean isEqual(VariableBinding variableBinding, VariableBinding variableBinding2) {
  122. return (variableBinding.modifiers & ExtraCompilerModifiers.AccJustFlag) == (variableBinding2.modifiers & ExtraCompilerModifiers.AccJustFlag)
  123. && CharOperation.equals(variableBinding.name, variableBinding2.name)
  124. && isEqual(variableBinding.type, variableBinding2.type)
  125. && (variableBinding.id == variableBinding2.id);
  126. }
  127. static boolean isEqual(FieldBinding fieldBinding, FieldBinding fieldBinding2) {
  128. HashSet visitedTypes= new HashSet();
  129. return (fieldBinding.modifiers & ExtraCompilerModifiers.AccJustFlag) == (fieldBinding2.modifiers & ExtraCompilerModifiers.AccJustFlag)
  130. && CharOperation.equals(fieldBinding.name, fieldBinding2.name)
  131. && isEqual(fieldBinding.type, fieldBinding2.type, visitedTypes)
  132. && isEqual(fieldBinding.declaringClass, fieldBinding2.declaringClass, visitedTypes);
  133. }
  134. /**
  135. * @param bindings
  136. * @param otherBindings
  137. * @return true if both parameters are equals, false otherwise
  138. */
  139. static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] bindings, org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] otherBindings) {
  140. return isEqual(bindings, otherBindings, new HashSet());
  141. }
  142. /**
  143. * @param bindings
  144. * @param otherBindings
  145. * @return true if both parameters are equals, false otherwise
  146. */
  147. static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] bindings, org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] otherBindings, HashSet visitedTypes) {
  148. if (bindings == null) {
  149. return otherBindings == null;
  150. }
  151. if (otherBindings == null) {
  152. return false;
  153. }
  154. int length= bindings.length;
  155. int otherLength= otherBindings.length;
  156. if (length != otherLength) {
  157. return false;
  158. }
  159. for (int i= 0; i < length; i++) {
  160. if (!isEqual(bindings[i], otherBindings[i], visitedTypes)) {
  161. return false;
  162. }
  163. }
  164. return true;
  165. }
  166. static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding2, HashSet visitedTypes) {
  167. if (typeBinding == typeBinding2)
  168. return true;
  169. if (typeBinding == null || typeBinding2 == null)
  170. return false;
  171. switch (typeBinding.kind()) {
  172. case Binding.BASE_TYPE:
  173. if (!typeBinding2.isBaseType()) {
  174. return false;
  175. }
  176. return typeBinding.id == typeBinding2.id;
  177. case Binding.ARRAY_TYPE:
  178. if (!typeBinding2.isArrayType()) {
  179. return false;
  180. }
  181. return typeBinding.dimensions() == typeBinding2.dimensions()
  182. && isEqual(typeBinding.leafComponentType(), typeBinding2.leafComponentType(), visitedTypes);
  183. case Binding.PARAMETERIZED_TYPE:
  184. if (!typeBinding2.isParameterizedType()) {
  185. return false;
  186. }
  187. ParameterizedTypeBinding parameterizedTypeBinding= (ParameterizedTypeBinding)typeBinding;
  188. ParameterizedTypeBinding parameterizedTypeBinding2= (ParameterizedTypeBinding)typeBinding2;
  189. return CharOperation.equals(parameterizedTypeBinding.compoundName, parameterizedTypeBinding2.compoundName)
  190. && (parameterizedTypeBinding.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
  191. == (parameterizedTypeBinding2.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
  192. && isEqual(parameterizedTypeBinding.arguments, parameterizedTypeBinding2.arguments, visitedTypes)
  193. && isEqual(parameterizedTypeBinding.enclosingType(), parameterizedTypeBinding2.enclosingType(), visitedTypes);
  194. case Binding.WILDCARD_TYPE:
  195. if (typeBinding2.kind() != Binding.WILDCARD_TYPE) {
  196. return false;
  197. }
  198. WildcardBinding wildcardBinding= (WildcardBinding)typeBinding;
  199. WildcardBinding wildcardBinding2= (WildcardBinding)typeBinding2;
  200. return isEqual(wildcardBinding.bound, wildcardBinding2.bound, visitedTypes)
  201. && wildcardBinding.boundKind == wildcardBinding2.boundKind;
  202. case Binding.INTERSECTION_TYPE:
  203. if (typeBinding2.kind() != Binding.INTERSECTION_TYPE) {
  204. return false;
  205. }
  206. WildcardBinding intersectionBinding= (WildcardBinding)typeBinding;
  207. WildcardBinding intersectionBinding2= (WildcardBinding)typeBinding2;
  208. return isEqual(intersectionBinding.bound, intersectionBinding2.bound, visitedTypes)
  209. && isEqual(intersectionBinding.otherBounds, intersectionBinding2.otherBounds, visitedTypes);
  210. case Binding.TYPE_PARAMETER:
  211. if (!(typeBinding2.isTypeVariable())) {
  212. return false;
  213. }
  214. if (typeBinding.isCapture()) {
  215. if (!(typeBinding2.isCapture())) {
  216. return false;
  217. }
  218. CaptureBinding captureBinding= (CaptureBinding)typeBinding;
  219. CaptureBinding captureBinding2= (CaptureBinding)typeBinding2;
  220. if (captureBinding.position == captureBinding2.position) {
  221. if (visitedTypes.contains(typeBinding))
  222. return true;
  223. visitedTypes.add(typeBinding);
  224. return isEqual(captureBinding.wildcard, captureBinding2.wildcard, visitedTypes)
  225. && isEqual(captureBinding.sourceType, captureBinding2.sourceType, visitedTypes);
  226. }
  227. return false;
  228. }
  229. TypeVariableBinding typeVariableBinding= (TypeVariableBinding)typeBinding;
  230. TypeVariableBinding typeVariableBinding2= (TypeVariableBinding)typeBinding2;
  231. if (CharOperation.equals(typeVariableBinding.sourceName, typeVariableBinding2.sourceName)) {
  232. if (visitedTypes.contains(typeBinding))
  233. return true;
  234. visitedTypes.add(typeBinding);
  235. return isEqual(typeVariableBinding.declaringElement, typeVariableBinding2.declaringElement, visitedTypes)
  236. && isEqual(typeVariableBinding.superclass(), typeVariableBinding2.superclass(), visitedTypes)
  237. && isEqual(typeVariableBinding.superInterfaces(), typeVariableBinding2.superInterfaces(), visitedTypes);
  238. }
  239. return false;
  240. case Binding.GENERIC_TYPE:
  241. if (!typeBinding2.isGenericType()) {
  242. return false;
  243. }
  244. ReferenceBinding referenceBinding= (ReferenceBinding)typeBinding;
  245. ReferenceBinding referenceBinding2= (ReferenceBinding)typeBinding2;
  246. return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
  247. && (referenceBinding.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
  248. == (referenceBinding2.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
  249. && isEqual(referenceBinding.typeVariables(), referenceBinding2.typeVariables(), visitedTypes)
  250. && isEqual(referenceBinding.enclosingType(), referenceBinding2.enclosingType(), visitedTypes);
  251. case Binding.RAW_TYPE:
  252. default:
  253. if (!(typeBinding2 instanceof ReferenceBinding)) {
  254. return false;
  255. }
  256. referenceBinding= (ReferenceBinding)typeBinding;
  257. referenceBinding2= (ReferenceBinding)typeBinding2;
  258. char[] constantPoolName= referenceBinding.constantPoolName();
  259. char[] constantPoolName2= referenceBinding2.constantPoolName();
  260. // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=116833
  261. if (constantPoolName == null) {
  262. if (constantPoolName2 != null) {
  263. return false;
  264. }
  265. if (!CharOperation.equals(referenceBinding.computeUniqueKey(), referenceBinding2.computeUniqueKey())) {
  266. return false;
  267. }
  268. } else {
  269. if (constantPoolName2 == null) {
  270. return false;
  271. }
  272. if (!CharOperation.equals(constantPoolName, constantPoolName2)) {
  273. return false;
  274. }
  275. }
  276. return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
  277. && (!referenceBinding2.isGenericType())
  278. && (referenceBinding.isRawType() == referenceBinding2.isRawType())
  279. && ((referenceBinding.modifiers & ~ClassFileConstants.AccSuper) & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
  280. == ((referenceBinding2.modifiers & ~ClassFileConstants.AccSuper) & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
  281. && isEqual(referenceBinding.enclosingType(), referenceBinding2.enclosingType(), visitedTypes);
  282. }
  283. }
  284. /**
  285. * @param typeBinding
  286. * @param typeBinding2
  287. * @return true if both parameters are equals, false otherwise
  288. */
  289. static boolean isEqual(org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding2) {
  290. return isEqual(typeBinding, typeBinding2, new HashSet());
  291. }
  292. }