001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.lookup;
011:
012: import org.eclipse.jdt.core.compiler.CharOperation;
013: import org.eclipse.jdt.internal.compiler.ast.Wildcard;
014: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
015:
016: /*
017: * A wildcard acts as an argument for parameterized types, allowing to
018: * abstract parameterized types, e.g. List<String> is not compatible with List<Object>,
019: * but compatible with List<?>.
020: */
021: public class WildcardBinding extends ReferenceBinding {
022:
023: ReferenceBinding genericType;
024: int rank;
025: public TypeBinding bound; // when unbound denotes the corresponding type variable (so as to retrieve its bound lazily)
026: public TypeBinding[] otherBounds; // only positionned by lub computations (if so, #bound is also set) and associated to EXTENDS mode
027: char[] genericSignature;
028: public int boundKind;
029: ReferenceBinding super class;
030: ReferenceBinding[] super Interfaces;
031: TypeVariableBinding typeVariable; // corresponding variable
032: LookupEnvironment environment;
033:
034: /**
035: * When unbound, the bound denotes the corresponding type variable (so as to retrieve its bound lazily)
036: */
037: public WildcardBinding(ReferenceBinding genericType, int rank,
038: TypeBinding bound, TypeBinding[] otherBounds,
039: int boundKind, LookupEnvironment environment) {
040: this .genericType = genericType;
041: this .rank = rank;
042: this .boundKind = boundKind;
043: this .modifiers = ClassFileConstants.AccPublic
044: | ExtraCompilerModifiers.AccGenericSignature; // treat wildcard as public
045: this .environment = environment;
046: initialize(genericType, bound, otherBounds);
047:
048: if (genericType instanceof UnresolvedReferenceBinding)
049: ((UnresolvedReferenceBinding) genericType).addWrapper(this ,
050: environment);
051: if (bound instanceof UnresolvedReferenceBinding)
052: ((UnresolvedReferenceBinding) bound).addWrapper(this ,
053: environment);
054: this .tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve()
055: }
056:
057: public int kind() {
058: return WILDCARD_TYPE;
059: }
060:
061: /**
062: * Returns true if the argument type satisfies the wildcard bound(s)
063: */
064: public boolean boundCheck(TypeBinding argumentType) {
065: switch (this .boundKind) {
066: case Wildcard.UNBOUND:
067: return true;
068: case Wildcard.EXTENDS:
069: if (argumentType.isCompatibleWith(this .bound))
070: return true;
071: // check other bounds (lub scenario)
072: for (int i = 0, length = this .otherBounds == null ? 0
073: : this .otherBounds.length; i < length; i++) {
074: if (argumentType.isCompatibleWith(this .otherBounds[i]))
075: return true;
076: }
077: return false;
078: default: // SUPER
079: // ? super Exception ok for: IOException, since it would be ok for (Exception)ioException
080: return argumentType.isCompatibleWith(this .bound);
081: }
082: }
083:
084: /**
085: * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
086: */
087: public boolean canBeInstantiated() {
088: // cannot be asked per construction
089: return false;
090: }
091:
092: /**
093: * Collect the substitutes into a map for certain type variables inside the receiver type
094: * e.g. Collection<T>.collectSubstitutes(Collection<List<X>>, Map), will populate Map with: T --> List<X>
095: * Constraints:
096: * A << F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EXTENDS (1))
097: * A = F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EQUAL (0))
098: * A >> F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER (2))
099: */
100: public void collectSubstitutes(Scope scope, TypeBinding actualType,
101: InferenceContext inferenceContext, int constraint) {
102:
103: if ((this .tagBits & TagBits.HasTypeVariable) == 0)
104: return;
105: if (actualType == TypeBinding.NULL)
106: return;
107:
108: if (actualType.isCapture()) {
109: CaptureBinding capture = (CaptureBinding) actualType;
110: actualType = capture.wildcard;
111: }
112:
113: switch (constraint) {
114: case TypeConstants.CONSTRAINT_EXTENDS: // A << F
115: switch (this .boundKind) {
116: case Wildcard.UNBOUND: // F={?}
117: // if (otherType.isWildcard()) {
118: // WildcardBinding otherWildcard = (WildcardBinding) otherType;
119: // switch(otherWildcard.kind) {
120: // case Wildcard.UNBOUND: // A={?} << F={?} --> 0
121: // break;
122: // case Wildcard.EXTENDS: // A={? extends V} << F={?} ---> 0
123: // break;
124: // case Wildcard.SUPER: // A={? super V} << F={?} ---> 0
125: // break;
126: // }
127: // } else { // A=V << F={?} ---> 0
128: // }
129: break;
130: case Wildcard.EXTENDS: // F={? extends U}
131: if (actualType.isWildcard()) {
132: WildcardBinding actualWildcard = (WildcardBinding) actualType;
133: switch (actualWildcard.boundKind) {
134: case Wildcard.UNBOUND: // A={?} << F={? extends U} --> 0
135: break;
136: case Wildcard.EXTENDS: // A={? extends V} << F={? extends U} ---> V << U
137: this .bound.collectSubstitutes(scope,
138: actualWildcard.bound, inferenceContext,
139: TypeConstants.CONSTRAINT_EXTENDS);
140: for (int i = 0, length = actualWildcard.otherBounds == null ? 0
141: : actualWildcard.otherBounds.length; i < length; i++) {
142: this .bound.collectSubstitutes(scope,
143: actualWildcard.otherBounds[i],
144: inferenceContext,
145: TypeConstants.CONSTRAINT_EXTENDS);
146: }
147: break;
148: case Wildcard.SUPER: // A={? super V} << F={? extends U} ---> 0
149: break;
150: }
151: } else { // A=V << F={? extends U} ---> V << U
152: this .bound.collectSubstitutes(scope, actualType,
153: inferenceContext,
154: TypeConstants.CONSTRAINT_EXTENDS);
155: }
156: break;
157: case Wildcard.SUPER: // F={? super U}
158: if (actualType.isWildcard()) {
159: WildcardBinding actualWildcard = (WildcardBinding) actualType;
160: switch (actualWildcard.boundKind) {
161: case Wildcard.UNBOUND: // A={?} << F={? super U} --> 0
162: break;
163: case Wildcard.EXTENDS: // A={? extends V} << F={? super U} ---> 0
164: break;
165: case Wildcard.SUPER: // A={? super V} << F={? super U} ---> 0
166: this .bound.collectSubstitutes(scope,
167: actualWildcard.bound, inferenceContext,
168: TypeConstants.CONSTRAINT_SUPER);
169: for (int i = 0, length = actualWildcard.otherBounds == null ? 0
170: : actualWildcard.otherBounds.length; i < length; i++) {
171: this .bound.collectSubstitutes(scope,
172: actualWildcard.otherBounds[i],
173: inferenceContext,
174: TypeConstants.CONSTRAINT_SUPER);
175: }
176: break;
177: }
178: } else { // A=V << F={? super U} ---> V >> U
179: this .bound.collectSubstitutes(scope, actualType,
180: inferenceContext,
181: TypeConstants.CONSTRAINT_SUPER);
182: }
183: break;
184: }
185: break;
186: case TypeConstants.CONSTRAINT_EQUAL: // A == F
187: switch (this .boundKind) {
188: case Wildcard.UNBOUND: // F={?}
189: // if (otherType.isWildcard()) {
190: // WildcardBinding otherWildcard = (WildcardBinding) otherType;
191: // switch(otherWildcard.kind) {
192: // case Wildcard.UNBOUND: // A={?} == F={?} --> 0
193: // break;
194: // case Wildcard.EXTENDS: // A={? extends V} == F={?} ---> 0
195: // break;
196: // case Wildcard.SUPER: // A={? super V} == F={?} ---> 0
197: // break;
198: // }
199: // } else { // A=V == F={?} ---> 0
200: // }
201: break;
202: case Wildcard.EXTENDS: // F={? extends U}
203: if (actualType.isWildcard()) {
204: WildcardBinding actualWildcard = (WildcardBinding) actualType;
205: switch (actualWildcard.boundKind) {
206: case Wildcard.UNBOUND: // A={?} == F={? extends U} --> 0
207: break;
208: case Wildcard.EXTENDS: // A={? extends V} == F={? extends U} ---> V == U
209: this .bound.collectSubstitutes(scope,
210: actualWildcard.bound, inferenceContext,
211: TypeConstants.CONSTRAINT_EQUAL);
212: for (int i = 0, length = actualWildcard.otherBounds == null ? 0
213: : actualWildcard.otherBounds.length; i < length; i++) {
214: this .bound.collectSubstitutes(scope,
215: actualWildcard.otherBounds[i],
216: inferenceContext,
217: TypeConstants.CONSTRAINT_EQUAL);
218: }
219: break;
220: case Wildcard.SUPER: // A={? super V} == F={? extends U} ---> 0
221: break;
222: }
223: } else { // A=V == F={? extends U} ---> 0
224: }
225: break;
226: case Wildcard.SUPER: // F={? super U}
227: if (actualType.isWildcard()) {
228: WildcardBinding actualWildcard = (WildcardBinding) actualType;
229: switch (actualWildcard.boundKind) {
230: case Wildcard.UNBOUND: // A={?} == F={? super U} --> 0
231: break;
232: case Wildcard.EXTENDS: // A={? extends V} == F={? super U} ---> 0
233: break;
234: case Wildcard.SUPER: // A={? super V} == F={? super U} ---> 0
235: this .bound.collectSubstitutes(scope,
236: actualWildcard.bound, inferenceContext,
237: TypeConstants.CONSTRAINT_EQUAL);
238: for (int i = 0, length = actualWildcard.otherBounds == null ? 0
239: : actualWildcard.otherBounds.length; i < length; i++) {
240: this .bound.collectSubstitutes(scope,
241: actualWildcard.otherBounds[i],
242: inferenceContext,
243: TypeConstants.CONSTRAINT_EQUAL);
244: }
245: break;
246: }
247: } else { // A=V == F={? super U} ---> 0
248: }
249: break;
250: }
251: break;
252: case TypeConstants.CONSTRAINT_SUPER: // A >> F
253: switch (this .boundKind) {
254: case Wildcard.UNBOUND: // F={?}
255: // if (otherType.isWildcard()) {
256: // WildcardBinding otherWildcard = (WildcardBinding) otherType;
257: // switch(otherWildcard.kind) {
258: // case Wildcard.UNBOUND: // A={?} >> F={?} --> 0
259: // break;
260: // case Wildcard.EXTENDS: // A={? extends V} >> F={?} ---> 0
261: // break;
262: // case Wildcard.SUPER: // A={? super V} >> F={?} ---> 0
263: // break;
264: // }
265: // } else { // A=V >> F={?} ---> 0
266: // }
267: break;
268: case Wildcard.EXTENDS: // F={? extends U}
269: if (actualType.isWildcard()) {
270: WildcardBinding actualWildcard = (WildcardBinding) actualType;
271: switch (actualWildcard.boundKind) {
272: case Wildcard.UNBOUND: // A={?} >> F={? extends U} --> 0
273: break;
274: case Wildcard.EXTENDS: // A={? extends V} >> F={? extends U} ---> V >> U
275: this .bound.collectSubstitutes(scope,
276: actualWildcard.bound, inferenceContext,
277: TypeConstants.CONSTRAINT_SUPER);
278: for (int i = 0, length = actualWildcard.otherBounds == null ? 0
279: : actualWildcard.otherBounds.length; i < length; i++) {
280: this .bound.collectSubstitutes(scope,
281: actualWildcard.otherBounds[i],
282: inferenceContext,
283: TypeConstants.CONSTRAINT_SUPER);
284: }
285: break;
286: case Wildcard.SUPER: // A={? super V} >> F={? extends U} ---> 0
287: break;
288: }
289: } else { // A=V == F={? extends U} ---> 0
290: }
291: break;
292: case Wildcard.SUPER: // F={? super U}
293: if (actualType.isWildcard()) {
294: WildcardBinding actualWildcard = (WildcardBinding) actualType;
295: switch (actualWildcard.boundKind) {
296: case Wildcard.UNBOUND: // A={?} >> F={? super U} --> 0
297: break;
298: case Wildcard.EXTENDS: // A={? extends V} >> F={? super U} ---> 0
299: break;
300: case Wildcard.SUPER: // A={? super V} >> F={? super U} ---> V >> U
301: this .bound.collectSubstitutes(scope,
302: actualWildcard.bound, inferenceContext,
303: TypeConstants.CONSTRAINT_SUPER);
304: for (int i = 0, length = actualWildcard.otherBounds == null ? 0
305: : actualWildcard.otherBounds.length; i < length; i++) {
306: this .bound.collectSubstitutes(scope,
307: actualWildcard.otherBounds[i],
308: inferenceContext,
309: TypeConstants.CONSTRAINT_SUPER);
310: }
311: break;
312: }
313: } else { // A=V >> F={? super U} ---> 0
314: }
315: break;
316: }
317: break;
318: }
319: }
320:
321: /*
322: * genericTypeKey *|+|- [boundKey]
323: * p.X<T> { X<?> ... } --> Lp/X<TT;>;*
324: */
325: public char[] computeUniqueKey(boolean isLeaf) {
326: char[] genericTypeKey = this .genericType
327: .computeUniqueKey(false/*not a leaf*/);
328: char[] wildCardKey;
329: switch (this .boundKind) {
330: case Wildcard.UNBOUND:
331: wildCardKey = TypeConstants.WILDCARD_STAR;
332: break;
333: case Wildcard.EXTENDS:
334: wildCardKey = CharOperation.concat(
335: TypeConstants.WILDCARD_PLUS, this .bound
336: .computeUniqueKey(false/*not a leaf*/));
337: break;
338: default: // SUPER
339: wildCardKey = CharOperation.concat(
340: TypeConstants.WILDCARD_MINUS, this .bound
341: .computeUniqueKey(false/*not a leaf*/));
342: break;
343: }
344: return CharOperation.concat(genericTypeKey, wildCardKey);
345: }
346:
347: /**
348: * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#constantPoolName()
349: */
350: public char[] constantPoolName() {
351: return this .erasure().constantPoolName();
352: }
353:
354: /**
355: * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
356: */
357: public String debugName() {
358: return toString();
359: }
360:
361: /* (non-Javadoc)
362: * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
363: */
364: public TypeBinding erasure() {
365: if (this .otherBounds == null) {
366: if (this .boundKind == Wildcard.EXTENDS)
367: return this .bound.erasure();
368: return typeVariable().erasure();
369: }
370: // intersection type
371: return this .bound.id == TypeIds.T_JavaLangObject ? this .otherBounds[0]
372: .erasure() // use first explicit bound to improve stackmap
373: : this .bound.erasure();
374: }
375:
376: /* (non-Javadoc)
377: * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
378: */
379: public char[] genericTypeSignature() {
380: if (this .genericSignature == null) {
381: switch (this .boundKind) {
382: case Wildcard.UNBOUND:
383: this .genericSignature = TypeConstants.WILDCARD_STAR;
384: break;
385: case Wildcard.EXTENDS:
386: this .genericSignature = CharOperation.concat(
387: TypeConstants.WILDCARD_PLUS, this .bound
388: .genericTypeSignature());
389: break;
390: default: // SUPER
391: this .genericSignature = CharOperation.concat(
392: TypeConstants.WILDCARD_MINUS, this .bound
393: .genericTypeSignature());
394: }
395: }
396: return this .genericSignature;
397: }
398:
399: public int hashCode() {
400: return this .genericType.hashCode();
401: }
402:
403: void initialize(ReferenceBinding someGenericType,
404: TypeBinding someBound, TypeBinding[] someOtherBounds) {
405: this .genericType = someGenericType;
406: this .bound = someBound;
407: this .otherBounds = someOtherBounds;
408: if (someGenericType != null) {
409: this .fPackage = someGenericType.getPackage();
410: }
411: if (someBound != null) {
412: this .tagBits |= someBound.tagBits & TagBits.HasTypeVariable;
413: }
414: }
415:
416: /**
417: * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#isSuperclassOf(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)
418: */
419: public boolean isSuperclassOf(ReferenceBinding otherType) {
420: if (this .boundKind == Wildcard.SUPER) {
421: if (this .bound instanceof ReferenceBinding) {
422: return ((ReferenceBinding) this .bound)
423: .isSuperclassOf(otherType);
424: } else { // array bound
425: return otherType.id == TypeIds.T_JavaLangObject;
426: }
427: }
428: return false;
429: }
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:
438: /**
439: * Returns true if the type is a wildcard
440: */
441: public boolean isUnboundWildcard() {
442: return this .boundKind == Wildcard.UNBOUND;
443: }
444:
445: /**
446: * Returns true if the type is a wildcard
447: */
448: public boolean isWildcard() {
449: return true;
450: }
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(
462: TypeConstants.WILDCARD_NAME,
463: TypeConstants.WILDCARD_EXTENDS, this .bound
464: .readableName());
465: StringBuffer buffer = new StringBuffer(10);
466: buffer.append(this .bound.readableName());
467: for (int i = 0, length = this .otherBounds.length; i < length; i++) {
468: buffer.append('&').append(
469: this .otherBounds[i].readableName());
470: }
471: int length;
472: char[] result = new char[length = buffer.length()];
473: buffer.getChars(0, length, result, 0);
474: return result;
475: default: // SUPER
476: return CharOperation.concat(TypeConstants.WILDCARD_NAME,
477: TypeConstants.WILDCARD_SUPER, this .bound
478: .readableName());
479: }
480: }
481:
482: ReferenceBinding resolve() {
483: if ((this .tagBits & TagBits.HasUnresolvedTypeVariables) == 0)
484: return this ;
485:
486: this .tagBits &= ~TagBits.HasUnresolvedTypeVariables;
487: BinaryTypeBinding.resolveType(this .genericType,
488: this .environment, null, 0);
489: switch (this .boundKind) {
490: case Wildcard.EXTENDS:
491: case Wildcard.SUPER:
492: BinaryTypeBinding.resolveType(this .bound, this .environment,
493: null, 0);
494: break;
495: case Wildcard.UNBOUND:
496: }
497: return this ;
498: }
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(
510: TypeConstants.WILDCARD_NAME,
511: TypeConstants.WILDCARD_EXTENDS, this .bound
512: .shortReadableName());
513: StringBuffer buffer = new StringBuffer(10);
514: buffer.append(this .bound.shortReadableName());
515: for (int i = 0, length = this .otherBounds.length; i < length; i++) {
516: buffer.append('&').append(
517: this .otherBounds[i].shortReadableName());
518: }
519: int length;
520: char[] result = new char[length = buffer.length()];
521: buffer.getChars(0, length, result, 0);
522: return result;
523: default: // SUPER
524: return CharOperation.concat(TypeConstants.WILDCARD_NAME,
525: TypeConstants.WILDCARD_SUPER, this .bound
526: .shortReadableName());
527: }
528: }
529:
530: /**
531: * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
532: */
533: public char[] signature() {
534: // should not be called directly on a wildcard; signature should only be asked on
535: // original methods or type erasures (which cannot denote wildcards at first level)
536: if (this .signature == null) {
537: switch (this .boundKind) {
538: case Wildcard.EXTENDS:
539: return this .bound.signature();
540: default: // SUPER | UNBOUND
541: return this .typeVariable().signature();
542: }
543: }
544: return this .signature;
545: }
546:
547: /* (non-Javadoc)
548: * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#sourceName()
549: */
550: public char[] sourceName() {
551: switch (this .boundKind) {
552: case Wildcard.UNBOUND:
553: return TypeConstants.WILDCARD_NAME;
554: case Wildcard.EXTENDS:
555: return CharOperation.concat(TypeConstants.WILDCARD_NAME,
556: TypeConstants.WILDCARD_EXTENDS, this .bound
557: .sourceName());
558: default: // SUPER
559: return CharOperation.concat(TypeConstants.WILDCARD_NAME,
560: TypeConstants.WILDCARD_SUPER, this .bound
561: .sourceName());
562: }
563: }
564:
565: /* (non-Javadoc)
566: * @see org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding#superclass()
567: */
568: public ReferenceBinding super class() {
569: if (this .super class == null) {
570: TypeBinding super Type = null;
571: if (this .boundKind == Wildcard.EXTENDS
572: && !this .bound.isInterface()) {
573: super Type = this .bound;
574: } else {
575: TypeVariableBinding variable = this .typeVariable();
576: if (variable != null)
577: super Type = variable.firstBound;
578: }
579: this .super class = super Type instanceof ReferenceBinding
580: && !super Type.isInterface() ? (ReferenceBinding) super Type
581: : environment.getResolvedType(
582: TypeConstants.JAVA_LANG_OBJECT, null);
583: }
584:
585: return this .super class;
586: }
587:
588: /*
589: public ReferenceBinding superclass2() {
590: if (this.superclass == null) {
591: TypeBinding superType = (this.boundKind == Wildcard.EXTENDS && !this.bound.isInterface())
592: ? this.bound
593: : null;
594: this.superclass = superType instanceof ReferenceBinding && !superType.isInterface()
595: ? (ReferenceBinding) superType
596: : environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
597:
598: // TypeBinding superType = null;
599: // if (this.boundKind == Wildcard.EXTENDS && !this.bound.isInterface()) {
600: // superType = this.bound;
601: // } else {
602: // TypeVariableBinding variable = this.typeVariable();
603: // if (variable != null) superType = variable.firstBound;
604: // }
605: // this.superclass = superType instanceof ReferenceBinding && !superType.isInterface()
606: // ? (ReferenceBinding) superType
607: // : environment.getType(TypeConstants.JAVA_LANG_OBJECT);
608: }
609: return this.superclass;
610: }
611: */
612: /* (non-Javadoc)
613: * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces()
614: */
615: public ReferenceBinding[] super Interfaces() {
616: if (this .super Interfaces == null) {
617: if (this .typeVariable() != null) {
618: this .super Interfaces = this .typeVariable
619: .super Interfaces();
620: } else {
621: this .super Interfaces = Binding.NO_SUPERINTERFACES;
622: }
623: if (this .boundKind == Wildcard.EXTENDS) {
624: if (this .bound.isInterface()) {
625: // augment super interfaces with the wildcard bound
626: int length = this .super Interfaces.length;
627: System
628: .arraycopy(
629: this .super Interfaces,
630: 0,
631: this .super Interfaces = new ReferenceBinding[length + 1],
632: 1, length);
633: this .super Interfaces[0] = (ReferenceBinding) this .bound; // make bound first
634: }
635: if (this .otherBounds != null) {
636: // augment super interfaces with the wildcard otherBounds (interfaces per construction)
637: int length = this .super Interfaces.length;
638: int otherLength = this .otherBounds.length;
639: System
640: .arraycopy(
641: this .super Interfaces,
642: 0,
643: this .super Interfaces = new ReferenceBinding[length
644: + otherLength], 0, length);
645: for (int i = 0; i < otherLength; i++) {
646: this .super Interfaces[length + i] = (ReferenceBinding) this .otherBounds[i];
647: }
648: }
649: }
650: }
651: return this .super Interfaces;
652: }
653:
654: public ReferenceBinding[] super Interfaces2() {
655: if (this .super Interfaces == null) {
656: if (this .boundKind == Wildcard.EXTENDS) {
657: if (this .bound.isInterface()) {
658: if (this .otherBounds != null) {
659: // augment super interfaces with the wildcard otherBounds (interfaces per construction)
660: int otherLength = this .otherBounds.length;
661: System
662: .arraycopy(
663: this .otherBounds,
664: 0,
665: this .super Interfaces = new ReferenceBinding[otherLength + 1],
666: 1, otherLength);
667: this .super Interfaces[0] = (ReferenceBinding) this .bound;
668: } else {
669: this .super Interfaces = new ReferenceBinding[] { (ReferenceBinding) this .bound };
670: }
671: } else if (this .otherBounds != null) {
672: int otherLength = this .otherBounds.length;
673: System
674: .arraycopy(
675: this .otherBounds,
676: 0,
677: this .super Interfaces = new ReferenceBinding[otherLength],
678: 0, otherLength);
679: } else {
680: this .super Interfaces = Binding.NO_SUPERINTERFACES;
681: }
682: } else {
683: this .super Interfaces = Binding.NO_SUPERINTERFACES;
684: }
685: }
686: return this .super Interfaces;
687: }
688:
689: public void swapUnresolved(
690: UnresolvedReferenceBinding unresolvedType,
691: ReferenceBinding resolvedType, LookupEnvironment env) {
692: boolean affected = false;
693: if (this .genericType == unresolvedType) {
694: this .genericType = resolvedType; // no raw conversion
695: affected = true;
696: } else if (this .bound == unresolvedType) {
697: this .bound = env
698: .convertUnresolvedBinaryToRawType(resolvedType);
699: affected = true;
700: }
701: if (affected)
702: initialize(this .genericType, this .bound, this .otherBounds);
703: }
704:
705: /**
706: * @see java.lang.Object#toString()
707: */
708: public String toString() {
709: switch (this .boundKind) {
710: case Wildcard.UNBOUND:
711: return new String(TypeConstants.WILDCARD_NAME);
712: case Wildcard.EXTENDS:
713: if (this .otherBounds == null)
714: return new String(CharOperation.concat(
715: TypeConstants.WILDCARD_NAME,
716: TypeConstants.WILDCARD_EXTENDS, this .bound
717: .debugName().toCharArray()));
718: StringBuffer buffer = new StringBuffer(this .bound
719: .debugName());
720: for (int i = 0, length = this .otherBounds.length; i < length; i++) {
721: buffer.append('&').append(
722: this .otherBounds[i].debugName());
723: }
724: return buffer.toString();
725: default: // SUPER
726: return new String(CharOperation.concat(
727: TypeConstants.WILDCARD_NAME,
728: TypeConstants.WILDCARD_SUPER, this .bound
729: .debugName().toCharArray()));
730: }
731: }
732:
733: /**
734: * Returns associated type variable, or null in case of inconsistency
735: */
736: public TypeVariableBinding typeVariable() {
737: if (this .typeVariable == null) {
738: TypeVariableBinding[] typeVariables = this.genericType
739: .typeVariables();
740: if (this.rank < typeVariables.length)
741: this.typeVariable = typeVariables[this.rank];
742: }
743: return this.typeVariable;
744: }
745: }
|