KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > lookup > CaptureBinding


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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
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 public class CaptureBinding extends TypeVariableBinding {
18     
19     public TypeBinding lowerBound;
20     public WildcardBinding wildcard;
21     public int captureID;
22     
23     /* information to compute unique binding key */
24     public ReferenceBinding sourceType;
25     public int position;
26     
27     public CaptureBinding(WildcardBinding wildcard, ReferenceBinding sourceType, int position, int captureID) {
28         super(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX, null, 0);
29         this.wildcard = wildcard;
30         this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat capture as public
31
this.fPackage = wildcard.fPackage;
32         this.sourceType = sourceType;
33         this.position = position;
34         this.captureID = captureID;
35     }
36
37     /*
38      * sourceTypeKey ! wildcardKey position semi-colon
39      * p.X { capture of ? } --> !*123; (Lp/X; in declaring type except if leaf)
40      * p.X { capture of ? extends p.Y } --> !+Lp/Y;123; (Lp/X; in declaring type except if leaf)
41      */

42     public char[] computeUniqueKey(boolean isLeaf) {
43         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
44         if (isLeaf) {
45             buffer.append(this.sourceType.computeUniqueKey(false/*not a leaf*/));
46             buffer.append('&');
47         }
48         buffer.append(TypeConstants.WILDCARD_CAPTURE);
49         buffer.append(this.wildcard.computeUniqueKey(false/*not a leaf*/));
50         buffer.append(this.position);
51         buffer.append(';');
52         int length = buffer.length();
53         char[] uniqueKey = new char[length];
54         buffer.getChars(0, length, uniqueKey, 0);
55         return uniqueKey;
56     }
57
58     public String JavaDoc debugName() {
59
60         if (this.wildcard != null) {
61             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(10);
62             buffer
63                 .append(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX)
64                 .append(this.captureID)
65                 .append(TypeConstants.WILDCARD_CAPTURE_NAME_SUFFIX)
66                 .append(this.wildcard.debugName());
67             return buffer.toString();
68         }
69         return super.debugName();
70     }
71     
72     public char[] genericTypeSignature() {
73         if (this.genericTypeSignature == null) {
74             this.genericTypeSignature = CharOperation.concat(TypeConstants.WILDCARD_CAPTURE, this.wildcard.genericTypeSignature());
75         }
76         return this.genericTypeSignature;
77     }
78
79     /**
80      * Initialize capture bounds using substituted supertypes
81      * e.g. given X<U, V extends X<U, V>>, capture(X<E,?>) = X<E,capture>, where capture extends X<E,capture>
82      */

83     public void initializeBounds(Scope scope, ParameterizedTypeBinding capturedParameterizedType) {
84         TypeVariableBinding wildcardVariable = wildcard.typeVariable();
85         ReferenceBinding originalVariableSuperclass = wildcardVariable.superclass;
86         ReferenceBinding substitutedVariableSuperclass = (ReferenceBinding) Scope.substitute(capturedParameterizedType, originalVariableSuperclass);
87         // prevent cyclic capture: given X<T>, capture(X<? extends T> could yield a circular type
88
if (substitutedVariableSuperclass == this) substitutedVariableSuperclass = originalVariableSuperclass;
89         
90         ReferenceBinding[] originalVariableInterfaces = wildcardVariable.superInterfaces();
91         ReferenceBinding[] substitutedVariableInterfaces = Scope.substitute(capturedParameterizedType, originalVariableInterfaces);
92         if (substitutedVariableInterfaces != originalVariableInterfaces) {
93             // prevent cyclic capture: given X<T>, capture(X<? extends T> could yield a circular type
94
for (int i = 0, length = substitutedVariableInterfaces.length; i < length; i++) {
95                 if (substitutedVariableInterfaces[i] == this) substitutedVariableInterfaces[i] = originalVariableInterfaces[i];
96             }
97         }
98         // no substitution for wildcard bound (only formal bounds from type variables are to be substituted: 104082)
99
TypeBinding originalWildcardBound = wildcard.bound;
100         
101         switch (wildcard.boundKind) {
102             case Wildcard.EXTENDS :
103                 // still need to capture bound supertype as well so as not to expose wildcards to the outside (111208)
104
TypeBinding substitutedWildcardBound = originalWildcardBound.capture(scope, this.position);
105                 if (wildcard.bound.isInterface()) {
106                     this.superclass = substitutedVariableSuperclass;
107                     // merge wildcard bound into variable superinterfaces using glb
108
if (substitutedVariableInterfaces == Binding.NO_SUPERINTERFACES) {
109                         this.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) substitutedWildcardBound };
110                     } else {
111                         int length = substitutedVariableInterfaces.length;
112                         System.arraycopy(substitutedVariableInterfaces, 0, substitutedVariableInterfaces = new ReferenceBinding[length+1], 1, length);
113                         substitutedVariableInterfaces[0] = (ReferenceBinding) substitutedWildcardBound;
114                         this.superInterfaces = Scope.greaterLowerBound(substitutedVariableInterfaces);
115                     }
116                 } else {
117                     // per construction the wildcard bound is a subtype of variable superclass
118
this.superclass = wildcard.bound.isArrayType() ? substitutedVariableSuperclass : (ReferenceBinding) substitutedWildcardBound;
119                     this.superInterfaces = substitutedVariableInterfaces;
120                 }
121                 this.firstBound = substitutedWildcardBound;
122                 if ((substitutedWildcardBound.tagBits & TagBits.HasTypeVariable) == 0)
123                     this.tagBits &= ~TagBits.HasTypeVariable;
124                 break;
125             case Wildcard.UNBOUND :
126                 this.superclass = substitutedVariableSuperclass;
127                 this.superInterfaces = substitutedVariableInterfaces;
128                 this.tagBits &= ~TagBits.HasTypeVariable;
129                 break;
130             case Wildcard.SUPER :
131                 this.superclass = substitutedVariableSuperclass;
132                 if (wildcardVariable.firstBound == substitutedVariableSuperclass || originalWildcardBound == substitutedVariableSuperclass) {
133                     this.firstBound = substitutedVariableSuperclass;
134                 }
135                 this.superInterfaces = substitutedVariableInterfaces;
136                 this.lowerBound = originalWildcardBound;
137                 if ((originalWildcardBound.tagBits & TagBits.HasTypeVariable) == 0)
138                     this.tagBits &= ~TagBits.HasTypeVariable;
139                 break;
140         }
141     }
142     
143     /**
144      * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isCapture()
145      */

146     public boolean isCapture() {
147         return true;
148     }
149     
150     /**
151      * @see TypeBinding#isEquivalentTo(TypeBinding)
152      */

153     public boolean isEquivalentTo(TypeBinding otherType) {
154         if (this == otherType) return true;
155         if (otherType == null) return false;
156         // capture of ? extends X[]
157
if (this.firstBound != null && this.firstBound.isArrayType()) {
158             if (this.firstBound.isCompatibleWith(otherType))
159                 return true;
160         }
161         if (otherType.isWildcard()) // wildcard
162
return ((WildcardBinding) otherType).boundCheck(this);
163         return false;
164     }
165
166     public char[] readableName() {
167         if (this.wildcard != null) {
168             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(10);
169             buffer
170                 .append(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX)
171                 .append(this.captureID)
172                 .append(TypeConstants.WILDCARD_CAPTURE_NAME_SUFFIX)
173                 .append(this.wildcard.readableName());
174             int length = buffer.length();
175             char[] name = new char[length];
176             buffer.getChars(0, length, name, 0);
177             return name;
178         }
179         return super.readableName();
180     }
181     
182     public char[] shortReadableName() {
183         if (this.wildcard != null) {
184             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(10);
185             buffer
186                 .append(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX)
187                 .append(this.captureID)
188                 .append(TypeConstants.WILDCARD_CAPTURE_NAME_SUFFIX)
189                 .append(this.wildcard.shortReadableName());
190             int length = buffer.length();
191             char[] name = new char[length];
192             buffer.getChars(0, length, name, 0);
193             return name;
194         }
195         return super.shortReadableName();
196     }
197     
198     public String JavaDoc toString() {
199         if (this.wildcard != null) {
200             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(10);
201             buffer
202                 .append(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX)
203                 .append(this.captureID)
204                 .append(TypeConstants.WILDCARD_CAPTURE_NAME_SUFFIX)
205                 .append(this.wildcard);
206             return buffer.toString();
207         }
208         return super.toString();
209     }
210 }
211
Popular Tags