PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/eclipse_SDK-3.7.1/plugins/org.eclipse.jdt.core.source_3.7.1.v_B76_R37x/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 689 lines | 499 code | 38 blank | 152 comment | 120 complexity | 7e1cb1136cd4416a1611b6b50b6d366e MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2005, 2009 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.internal.compiler.lookup;
  12. import java.util.List;
  13. import org.eclipse.jdt.core.compiler.CharOperation;
  14. import org.eclipse.jdt.internal.compiler.ast.Wildcard;
  15. import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
  16. /*
  17. * A wildcard acts as an argument for parameterized types, allowing to
  18. * abstract parameterized types, e.g. List<String> is not compatible with List<Object>,
  19. * but compatible with List<?>.
  20. */
  21. public class WildcardBinding extends ReferenceBinding {
  22. public ReferenceBinding genericType;
  23. public int rank;
  24. public TypeBinding bound; // when unbound denotes the corresponding type variable (so as to retrieve its bound lazily)
  25. public TypeBinding[] otherBounds; // only positionned by lub computations (if so, #bound is also set) and associated to EXTENDS mode
  26. char[] genericSignature;
  27. public int boundKind;
  28. ReferenceBinding superclass;
  29. ReferenceBinding[] superInterfaces;
  30. TypeVariableBinding typeVariable; // corresponding variable
  31. LookupEnvironment environment;
  32. /**
  33. * When unbound, the bound denotes the corresponding type variable (so as to retrieve its bound lazily)
  34. */
  35. public WildcardBinding(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind, LookupEnvironment environment) {
  36. this.rank = rank;
  37. this.boundKind = boundKind;
  38. this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat wildcard as public
  39. this.environment = environment;
  40. initialize(genericType, bound, otherBounds);
  41. // if (!genericType.isGenericType() && !(genericType instanceof UnresolvedReferenceBinding)) {
  42. // RuntimeException e = new RuntimeException("WILDCARD with NON GENERIC");
  43. // e.printStackTrace();
  44. // throw e;
  45. // }
  46. if (genericType instanceof UnresolvedReferenceBinding)
  47. ((UnresolvedReferenceBinding) genericType).addWrapper(this, environment);
  48. if (bound instanceof UnresolvedReferenceBinding)
  49. ((UnresolvedReferenceBinding) bound).addWrapper(this, environment);
  50. this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve()
  51. }
  52. public int kind() {
  53. return this.otherBounds == null ? Binding.WILDCARD_TYPE : Binding.INTERSECTION_TYPE;
  54. }
  55. /**
  56. * Returns true if the argument type satisfies the wildcard bound(s)
  57. */
  58. public boolean boundCheck(TypeBinding argumentType) {
  59. switch (this.boundKind) {
  60. case Wildcard.UNBOUND :
  61. return true;
  62. case Wildcard.EXTENDS :
  63. if (!argumentType.isCompatibleWith(this.bound)) return false;
  64. // check other bounds (lub scenario)
  65. for (int i = 0, length = this.otherBounds == null ? 0 : this.otherBounds.length; i < length; i++) {
  66. if (!argumentType.isCompatibleWith(this.otherBounds[i])) return false;
  67. }
  68. return true;
  69. default: // SUPER
  70. // ? super Exception ok for: IOException, since it would be ok for (Exception)ioException
  71. return argumentType.isCompatibleWith(this.bound);
  72. }
  73. }
  74. /**
  75. * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
  76. */
  77. public boolean canBeInstantiated() {
  78. // cannot be asked per construction
  79. return false;
  80. }
  81. /**
  82. * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#collectMissingTypes(java.util.List)
  83. */
  84. public List collectMissingTypes(List missingTypes) {
  85. if ((this.tagBits & TagBits.HasMissingType) != 0) {
  86. missingTypes = this.bound.collectMissingTypes(missingTypes);
  87. }
  88. return missingTypes;
  89. }
  90. /**
  91. * Collect the substitutes into a map for certain type variables inside the receiver type
  92. * e.g. Collection<T>.collectSubstitutes(Collection<List<X>>, Map), will populate Map with: T --> List<X>
  93. * Constraints:
  94. * A << F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EXTENDS (1))
  95. * A = F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EQUAL (0))
  96. * A >> F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER (2))
  97. */
  98. public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) {
  99. if ((this.tagBits & TagBits.HasTypeVariable) == 0) return;
  100. if (actualType == TypeBinding.NULL) return;
  101. if (actualType.isCapture()) {
  102. CaptureBinding capture = (CaptureBinding) actualType;
  103. actualType = capture.wildcard;
  104. }
  105. switch (constraint) {
  106. case TypeConstants.CONSTRAINT_EXTENDS : // A << F
  107. switch (this.boundKind) {
  108. case Wildcard.UNBOUND: // F={?}
  109. // switch (actualType.kind()) {
  110. // case Binding.WILDCARD_TYPE :
  111. // WildcardBinding actualWildcard = (WildcardBinding) actualType;
  112. // switch(actualWildcard.kind) {
  113. // case Wildcard.UNBOUND: // A={?} << F={?} --> 0
  114. // break;
  115. // case Wildcard.EXTENDS: // A={? extends V} << F={?} ---> 0
  116. // break;
  117. // case Wildcard.SUPER: // A={? super V} << F={?} ---> 0
  118. // break;
  119. // }
  120. // break;
  121. // case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} << F={?} ---> 0
  122. // break;
  123. // default :// A=V << F={?} ---> 0
  124. // break;
  125. // }
  126. break;
  127. case Wildcard.EXTENDS: // F={? extends U}
  128. switch(actualType.kind()) {
  129. case Binding.WILDCARD_TYPE :
  130. WildcardBinding actualWildcard = (WildcardBinding) actualType;
  131. switch(actualWildcard.boundKind) {
  132. case Wildcard.UNBOUND: // A={?} << F={? extends U} --> 0
  133. break;
  134. case Wildcard.EXTENDS: // A={? extends V} << F={? extends U} ---> V << U
  135. this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
  136. break;
  137. case Wildcard.SUPER: // A={? super V} << F={? extends U} ---> 0
  138. break;
  139. }
  140. break;
  141. case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} << F={? extends U} ---> V1 << U, ..., Vn << U
  142. WildcardBinding actualIntersection = (WildcardBinding) actualType;
  143. this.bound.collectSubstitutes(scope, actualIntersection.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
  144. for (int i = 0, length = actualIntersection.otherBounds.length; i < length; i++) {
  145. this.bound.collectSubstitutes(scope, actualIntersection.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
  146. }
  147. break;
  148. default : // A=V << F={? extends U} ---> V << U
  149. this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
  150. break;
  151. }
  152. break;
  153. case Wildcard.SUPER: // F={? super U}
  154. switch (actualType.kind()) {
  155. case Binding.WILDCARD_TYPE :
  156. WildcardBinding actualWildcard = (WildcardBinding) actualType;
  157. switch(actualWildcard.boundKind) {
  158. case Wildcard.UNBOUND: // A={?} << F={? super U} --> 0
  159. break;
  160. case Wildcard.EXTENDS: // A={? extends V} << F={? super U} ---> 0
  161. break;
  162. case Wildcard.SUPER: // A={? super V} << F={? super U} ---> 0
  163. this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
  164. for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
  165. this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER);
  166. }
  167. break;
  168. }
  169. break;
  170. case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} << F={? super U} ---> 0
  171. break;
  172. default :// A=V << F={? super U} ---> V >> U
  173. this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
  174. break;
  175. }
  176. break;
  177. }
  178. break;
  179. case TypeConstants.CONSTRAINT_EQUAL : // A == F
  180. switch (this.boundKind) {
  181. case Wildcard.UNBOUND: // F={?}
  182. // switch (actualType.kind()) {
  183. // case Binding.WILDCARD_TYPE :
  184. // WildcardBinding actualWildcard = (WildcardBinding) actualType;
  185. // switch(actualWildcard.kind) {
  186. // case Wildcard.UNBOUND: // A={?} == F={?} --> 0
  187. // break;
  188. // case Wildcard.EXTENDS: // A={? extends V} == F={?} ---> 0
  189. // break;
  190. // case Wildcard.SUPER: // A={? super V} == F={?} ---> 0
  191. // break;
  192. // }
  193. // break;
  194. // case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} == F={?} ---> 0
  195. // break;
  196. // default :// A=V == F={?} ---> 0
  197. // break;
  198. // }
  199. break;
  200. case Wildcard.EXTENDS: // F={? extends U}
  201. switch (actualType.kind()) {
  202. case Binding.WILDCARD_TYPE :
  203. WildcardBinding actualWildcard = (WildcardBinding) actualType;
  204. switch(actualWildcard.boundKind) {
  205. case Wildcard.UNBOUND: // A={?} == F={? extends U} --> 0
  206. break;
  207. case Wildcard.EXTENDS: // A={? extends V} == F={? extends U} ---> V == U
  208. this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
  209. for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
  210. this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
  211. }
  212. break;
  213. case Wildcard.SUPER: // A={? super V} == F={? extends U} ---> 0
  214. break;
  215. }
  216. break;
  217. case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} == F={? extends U} ---> V1 == U, ..., Vn == U
  218. WildcardBinding actuaIntersection = (WildcardBinding) actualType;
  219. this.bound.collectSubstitutes(scope, actuaIntersection.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
  220. for (int i = 0, length = actuaIntersection.otherBounds == null ? 0 : actuaIntersection.otherBounds.length; i < length; i++) {
  221. this.bound.collectSubstitutes(scope, actuaIntersection.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
  222. }
  223. break;
  224. default : // A=V == F={? extends U} ---> 0
  225. break;
  226. }
  227. break;
  228. case Wildcard.SUPER: // F={? super U}
  229. switch (actualType.kind()) {
  230. case Binding.WILDCARD_TYPE :
  231. WildcardBinding actualWildcard = (WildcardBinding) actualType;
  232. switch(actualWildcard.boundKind) {
  233. case Wildcard.UNBOUND: // A={?} == F={? super U} --> 0
  234. break;
  235. case Wildcard.EXTENDS: // A={? extends V} == F={? super U} ---> 0
  236. break;
  237. case Wildcard.SUPER: // A={? super V} == F={? super U} ---> 0
  238. this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
  239. for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
  240. this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
  241. }
  242. break;
  243. }
  244. break;
  245. case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} == F={? super U} ---> 0
  246. break;
  247. default : // A=V == F={? super U} ---> 0
  248. break;
  249. }
  250. break;
  251. }
  252. break;
  253. case TypeConstants.CONSTRAINT_SUPER : // A >> F
  254. switch (this.boundKind) {
  255. case Wildcard.UNBOUND: // F={?}
  256. // switch (actualType.kind()) {
  257. // case Binding.WILDCARD_TYPE :
  258. // WildcardBinding actualWildcard = (WildcardBinding) actualType;
  259. // switch(actualWildcard.kind) {
  260. // case Wildcard.UNBOUND: // A={?} >> F={?} --> 0
  261. // break;
  262. // case Wildcard.EXTENDS: // A={? extends V} >> F={?} ---> 0
  263. // break;
  264. // case Wildcard.SUPER: // A={? super V} >> F={?} ---> 0
  265. // break;
  266. // }
  267. // break;
  268. // case Binding.INTERSECTION_TYPE :// A={? extends V1&...&Vn} >> F={?} ---> 0
  269. // break;
  270. // default :// A=V >> F={?} ---> 0
  271. // break;
  272. // }
  273. break;
  274. case Wildcard.EXTENDS: // F={? extends U}
  275. switch (actualType.kind()) {
  276. case Binding.WILDCARD_TYPE :
  277. WildcardBinding actualWildcard = (WildcardBinding) actualType;
  278. switch(actualWildcard.boundKind) {
  279. case Wildcard.UNBOUND: // A={?} >> F={? extends U} --> 0
  280. break;
  281. case Wildcard.EXTENDS: // A={? extends V} >> F={? extends U} ---> V >> U
  282. this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
  283. for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
  284. this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER);
  285. }
  286. break;
  287. case Wildcard.SUPER: // A={? super V} >> F={? extends U} ---> 0
  288. break;
  289. }
  290. break;
  291. case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} >> F={? extends U} ---> V1 >> U, ..., Vn >> U
  292. WildcardBinding actualIntersection = (WildcardBinding) actualType;
  293. this.bound.collectSubstitutes(scope, actualIntersection.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
  294. for (int i = 0, length = actualIntersection.otherBounds == null ? 0 : actualIntersection.otherBounds.length; i < length; i++) {
  295. this.bound.collectSubstitutes(scope, actualIntersection.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER);
  296. }
  297. break;
  298. default : // A=V == F={? extends U} ---> 0
  299. break;
  300. }
  301. break;
  302. case Wildcard.SUPER: // F={? super U}
  303. switch (actualType.kind()) {
  304. case Binding.WILDCARD_TYPE :
  305. WildcardBinding actualWildcard = (WildcardBinding) actualType;
  306. switch(actualWildcard.boundKind) {
  307. case Wildcard.UNBOUND: // A={?} >> F={? super U} --> 0
  308. break;
  309. case Wildcard.EXTENDS: // A={? extends V} >> F={? super U} ---> 0
  310. break;
  311. case Wildcard.SUPER: // A={? super V} >> F={? super U} ---> V >> U
  312. this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
  313. for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
  314. this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER);
  315. }
  316. break;
  317. }
  318. break;
  319. case Binding.INTERSECTION_TYPE : // A={? extends V1&...&Vn} >> F={? super U} ---> 0
  320. break;
  321. default : // A=V >> F={? super U} ---> 0
  322. break;
  323. }
  324. break;
  325. }
  326. break;
  327. }
  328. }
  329. /*
  330. * genericTypeKey {rank}*|+|- [boundKey]
  331. * p.X<T> { X<?> ... } --> Lp/X<TT;>;{0}*
  332. */
  333. public char[] computeUniqueKey(boolean isLeaf) {
  334. char[] genericTypeKey = this.genericType.computeUniqueKey(false/*not a leaf*/);
  335. char[] wildCardKey;
  336. // We now encode the rank also in the binding key - https://bugs.eclipse.org/bugs/show_bug.cgi?id=234609
  337. char[] rankComponent = ('{' + String.valueOf(this.rank) + '}').toCharArray();
  338. switch (this.boundKind) {
  339. case Wildcard.UNBOUND :
  340. wildCardKey = TypeConstants.WILDCARD_STAR;
  341. break;
  342. case Wildcard.EXTENDS :
  343. wildCardKey = CharOperation.concat(TypeConstants.WILDCARD_PLUS, this.bound.computeUniqueKey(false/*not a leaf*/));
  344. break;
  345. default: // SUPER
  346. wildCardKey = CharOperation.concat(TypeConstants.WILDCARD_MINUS, this.bound.computeUniqueKey(false/*not a leaf*/));
  347. break;
  348. }
  349. return CharOperation.concat(genericTypeKey, rankComponent, wildCardKey);
  350. }
  351. /**
  352. * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#constantPoolName()
  353. */
  354. public char[] constantPoolName() {
  355. return erasure().constantPoolName();
  356. }
  357. /**
  358. * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
  359. */
  360. public String debugName() {
  361. return toString();
  362. }
  363. /* (non-Javadoc)
  364. * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
  365. */
  366. public TypeBinding erasure() {
  367. if (this.otherBounds == null) {
  368. if (this.boundKind == Wildcard.EXTENDS)
  369. return this.bound.erasure();
  370. TypeVariableBinding var = typeVariable();
  371. if (var != null)
  372. return var.erasure();
  373. return this.genericType; // if typeVariable() == null, then its inconsistent & return this.genericType to avoid NPE case
  374. }
  375. // intersection type
  376. return this.bound.id == TypeIds.T_JavaLangObject
  377. ? this.otherBounds[0].erasure() // use first explicit bound to improve stackmap
  378. : this.bound.erasure();
  379. }
  380. /* (non-Javadoc)
  381. * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
  382. */
  383. public char[] genericTypeSignature() {
  384. if (this.genericSignature == null) {
  385. switch (this.boundKind) {
  386. case Wildcard.UNBOUND :
  387. this.genericSignature = TypeConstants.WILDCARD_STAR;
  388. break;
  389. case Wildcard.EXTENDS :
  390. this.genericSignature = CharOperation.concat(TypeConstants.WILDCARD_PLUS, this.bound.genericTypeSignature());
  391. break;
  392. default: // SUPER
  393. this.genericSignature = CharOperation.concat(TypeConstants.WILDCARD_MINUS, this.bound.genericTypeSignature());
  394. }
  395. }
  396. return this.genericSignature;
  397. }
  398. public int hashCode() {
  399. return this.genericType.hashCode();
  400. }
  401. void initialize(ReferenceBinding someGenericType, TypeBinding someBound, TypeBinding[] someOtherBounds) {
  402. this.genericType = someGenericType;
  403. this.bound = someBound;
  404. this.otherBounds = someOtherBounds;
  405. if (someGenericType != null) {
  406. this.fPackage = someGenericType.getPackage();
  407. }
  408. if (someBound != null) {
  409. this.tagBits |= someBound.tagBits & (TagBits.HasTypeVariable | TagBits.HasMissingType | TagBits.ContainsNestedTypeReferences);
  410. }
  411. if (someOtherBounds != null) {
  412. for (int i = 0, max = someOtherBounds.length; i < max; i++) {
  413. TypeBinding someOtherBound = someOtherBounds[i];
  414. this.tagBits |= someOtherBound.tagBits & TagBits.ContainsNestedTypeReferences;
  415. }
  416. }
  417. }
  418. /**
  419. * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#isSuperclassOf(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)
  420. */
  421. public boolean isSuperclassOf(ReferenceBinding otherType) {
  422. if (this.boundKind == Wildcard.SUPER) {
  423. if (this.bound instanceof ReferenceBinding) {
  424. return ((ReferenceBinding) this.bound).isSuperclassOf(otherType);
  425. } else { // array bound
  426. return otherType.id == TypeIds.T_JavaLangObject;
  427. }
  428. }
  429. return false;
  430. }
  431. /**
  432. * Returns true if the current type denotes an intersection type: Number & Comparable<?>
  433. */
  434. public boolean isIntersectionType() {
  435. return this.otherBounds != null;
  436. }
  437. public boolean isHierarchyConnected() {
  438. return this.superclass != null && this.superInterfaces != null;
  439. }
  440. /**
  441. * Returns true if the type is a wildcard
  442. */
  443. public boolean isUnboundWildcard() {
  444. return this.boundKind == Wildcard.UNBOUND;
  445. }
  446. /**
  447. * Returns true if the type is a wildcard
  448. */
  449. public boolean isWildcard() {
  450. return true;
  451. }
  452. /* (non-Javadoc)
  453. * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
  454. */
  455. public char[] readableName() {
  456. switch (this.boundKind) {
  457. case Wildcard.UNBOUND :
  458. return TypeConstants.WILDCARD_NAME;
  459. case Wildcard.EXTENDS :
  460. if (this.otherBounds == null)
  461. return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.readableName());
  462. StringBuffer buffer = new StringBuffer(10);
  463. buffer.append(this.bound.readableName());
  464. for (int i = 0, length = this.otherBounds.length; i < length; i++) {
  465. buffer.append('&').append(this.otherBounds[i].readableName());
  466. }
  467. int length;
  468. char[] result = new char[length = buffer.length()];
  469. buffer.getChars(0, length, result, 0);
  470. return result;
  471. default: // SUPER
  472. return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.readableName());
  473. }
  474. }
  475. ReferenceBinding resolve() {
  476. if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0)
  477. return this;
  478. this.tagBits &= ~TagBits.HasUnresolvedTypeVariables;
  479. BinaryTypeBinding.resolveType(this.genericType, this.environment, false /* no raw conversion */);
  480. switch(this.boundKind) {
  481. case Wildcard.EXTENDS :
  482. TypeBinding resolveType = BinaryTypeBinding.resolveType(this.bound, this.environment, true /* raw conversion */);
  483. this.bound = resolveType;
  484. this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences;
  485. for (int i = 0, length = this.otherBounds == null ? 0 : this.otherBounds.length; i < length; i++) {
  486. resolveType = BinaryTypeBinding.resolveType(this.otherBounds[i], this.environment, true /* raw conversion */);
  487. this.otherBounds[i]= resolveType;
  488. this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences;
  489. }
  490. break;
  491. case Wildcard.SUPER :
  492. resolveType = BinaryTypeBinding.resolveType(this.bound, this.environment, true /* raw conversion */);
  493. this.bound = resolveType;
  494. this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences;
  495. break;
  496. case Wildcard.UNBOUND :
  497. }
  498. return this;
  499. }
  500. /* (non-Javadoc)
  501. * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
  502. */
  503. public char[] shortReadableName() {
  504. switch (this.boundKind) {
  505. case Wildcard.UNBOUND :
  506. return TypeConstants.WILDCARD_NAME;
  507. case Wildcard.EXTENDS :
  508. if (this.otherBounds == null)
  509. return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.shortReadableName());
  510. StringBuffer buffer = new StringBuffer(10);
  511. buffer.append(this.bound.shortReadableName());
  512. for (int i = 0, length = this.otherBounds.length; i < length; i++) {
  513. buffer.append('&').append(this.otherBounds[i].shortReadableName());
  514. }
  515. int length;
  516. char[] result = new char[length = buffer.length()];
  517. buffer.getChars(0, length, result, 0);
  518. return result;
  519. default: // SUPER
  520. return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.shortReadableName());
  521. }
  522. }
  523. /**
  524. * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
  525. */
  526. public char[] signature() {
  527. // should not be called directly on a wildcard; signature should only be asked on
  528. // original methods or type erasures (which cannot denote wildcards at first level)
  529. if (this.signature == null) {
  530. switch (this.boundKind) {
  531. case Wildcard.EXTENDS :
  532. return this.bound.signature();
  533. default: // SUPER | UNBOUND
  534. return typeVariable().signature();
  535. }
  536. }
  537. return this.signature;
  538. }
  539. /* (non-Javadoc)
  540. * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#sourceName()
  541. */
  542. public char[] sourceName() {
  543. switch (this.boundKind) {
  544. case Wildcard.UNBOUND :
  545. return TypeConstants.WILDCARD_NAME;
  546. case Wildcard.EXTENDS :
  547. return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.sourceName());
  548. default: // SUPER
  549. return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.sourceName());
  550. }
  551. }
  552. /* (non-Javadoc)
  553. * @see org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding#superclass()
  554. */
  555. public ReferenceBinding superclass() {
  556. if (this.superclass == null) {
  557. TypeBinding superType = null;
  558. if (this.boundKind == Wildcard.EXTENDS && !this.bound.isInterface()) {
  559. superType = this.bound;
  560. } else {
  561. TypeVariableBinding variable = typeVariable();
  562. if (variable != null) superType = variable.firstBound;
  563. }
  564. this.superclass = superType instanceof ReferenceBinding && !superType.isInterface()
  565. ? (ReferenceBinding) superType
  566. : this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
  567. }
  568. return this.superclass;
  569. }
  570. /* (non-Javadoc)
  571. * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces()
  572. */
  573. public ReferenceBinding[] superInterfaces() {
  574. if (this.superInterfaces == null) {
  575. if (typeVariable() != null) {
  576. this.superInterfaces = this.typeVariable.superInterfaces();
  577. } else {
  578. this.superInterfaces = Binding.NO_SUPERINTERFACES;
  579. }
  580. if (this.boundKind == Wildcard.EXTENDS) {
  581. if (this.bound.isInterface()) {
  582. // augment super interfaces with the wildcard bound
  583. int length = this.superInterfaces.length;
  584. System.arraycopy(this.superInterfaces, 0, this.superInterfaces = new ReferenceBinding[length+1], 1, length);
  585. this.superInterfaces[0] = (ReferenceBinding) this.bound; // make bound first
  586. }
  587. if (this.otherBounds != null) {
  588. // augment super interfaces with the wildcard otherBounds (interfaces per construction)
  589. int length = this.superInterfaces.length;
  590. int otherLength = this.otherBounds.length;
  591. System.arraycopy(this.superInterfaces, 0, this.superInterfaces = new ReferenceBinding[length+otherLength], 0, length);
  592. for (int i = 0; i < otherLength; i++) {
  593. this.superInterfaces[length+i] = (ReferenceBinding) this.otherBounds[i];
  594. }
  595. }
  596. }
  597. }
  598. return this.superInterfaces;
  599. }
  600. public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
  601. boolean affected = false;
  602. if (this.genericType == unresolvedType) {
  603. this.genericType = resolvedType; // no raw conversion
  604. affected = true;
  605. }
  606. if (this.bound == unresolvedType) {
  607. this.bound = env.convertUnresolvedBinaryToRawType(resolvedType);
  608. affected = true;
  609. }
  610. if (this.otherBounds != null) {
  611. for (int i = 0, length = this.otherBounds.length; i < length; i++) {
  612. if (this.otherBounds[i] == unresolvedType) {
  613. this.otherBounds[i] = env.convertUnresolvedBinaryToRawType(resolvedType);
  614. affected = true;
  615. }
  616. }
  617. }
  618. if (affected)
  619. initialize(this.genericType, this.bound, this.otherBounds);
  620. }
  621. /**
  622. * @see java.lang.Object#toString()
  623. */
  624. public String toString() {
  625. switch (this.boundKind) {
  626. case Wildcard.UNBOUND :
  627. return new String(TypeConstants.WILDCARD_NAME);
  628. case Wildcard.EXTENDS :
  629. if (this.otherBounds == null)
  630. return new String(CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.debugName().toCharArray()));
  631. StringBuffer buffer = new StringBuffer(this.bound.debugName());
  632. for (int i = 0, length = this.otherBounds.length; i < length; i++) {
  633. buffer.append('&').append(this.otherBounds[i].debugName());
  634. }
  635. return buffer.toString();
  636. default: // SUPER
  637. return new String(CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.debugName().toCharArray()));
  638. }
  639. }
  640. /**
  641. * Returns associated type variable, or null in case of inconsistency
  642. */
  643. public TypeVariableBinding typeVariable() {
  644. if (this.typeVariable == null) {
  645. TypeVariableBinding[] typeVariables = this.genericType.typeVariables();
  646. if (this.rank < typeVariables.length)
  647. this.typeVariable = typeVariables[this.rank];
  648. }
  649. return this.typeVariable;
  650. }
  651. }