added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / lookup / RawTypeBinding.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-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
16 /**
17  * Denote a raw type, i.e. a generic type referenced without any type arguments.
18  * e.g. X<T extends Exception> can be used a raw type 'X', in which case it
19  *      will behave as X<Exception>
20  */
21 public class RawTypeBinding extends ParameterizedTypeBinding {
22     
23     /**
24      * Raw type arguments are erasure of respective parameter bounds. But we may not have resolved
25      * these bounds yet if creating raw types while supertype hierarchies are being connected.
26      * Therefore, use 'null' instead, and access these in a lazy way later on (when substituting).
27      */
28         public RawTypeBinding(ReferenceBinding type, ReferenceBinding enclosingType, LookupEnvironment environment){
29                 super(type, null, enclosingType, environment);
30                 if (enclosingType == null || (enclosingType.modifiers & AccGenericSignature) == 0)
31                         this.modifiers &= ~AccGenericSignature; // only need signature if enclosing needs one
32         }    
33         /**
34          * @see org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding#createParameterizedMethod(org.eclipse.jdt.internal.compiler.lookup.MethodBinding)
35          */
36         public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
37                 if (originalMethod.typeVariables == NoTypeVariables || originalMethod.isStatic()) {
38                         return super.createParameterizedMethod(originalMethod);
39                 }
40                 return new ParameterizedGenericMethodBinding(originalMethod, this, this.environment);
41         }
42         
43         public int kind() {
44                 return RAW_TYPE;
45         }       
46         
47         /**
48          * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
49          */
50         public String debugName() {
51             StringBuffer nameBuffer = new StringBuffer(10);
52                 nameBuffer.append(this.type.sourceName()).append("#RAW"); //$NON-NLS-1$
53             return nameBuffer.toString();               
54         }       
55
56         /**
57          * Ltype<param1 ... paramN>;
58          * LY<TT;>;
59          */
60         public char[] genericTypeSignature() {
61
62             if (this.genericTypeSignature == null) {
63                     StringBuffer sig = new StringBuffer(10);
64                         if (this.isMemberType() && this.enclosingType().isParameterizedType()) {
65                             char[] typeSig = this.enclosingType().genericTypeSignature();
66                             for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
67                             sig.append('.').append(this.sourceName()).append(';');
68                                 int sigLength = sig.length();
69                                 this.genericTypeSignature = new char[sigLength];
70                                 sig.getChars(0, sigLength, this.genericTypeSignature, 0);                                                   
71                         } else {
72                              this.genericTypeSignature = this.type.signature(); // erasure
73                         }
74             }
75            return this.genericTypeSignature;
76         }               
77         
78     public boolean isEquivalentTo(TypeBinding otherType) {
79             if (this == otherType) return true;
80         if (otherType == null) return false;
81                 if (otherType.isWildcard()) // wildcard
82                         return ((WildcardBinding) otherType).boundCheck(this);
83         return otherType.erasure() == this.erasure();
84     }
85         /**
86          * Raw type is not treated as a standard parameterized type
87          * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isParameterizedType()
88          */
89         public boolean isParameterizedType() {
90             return false;
91         }       
92         public boolean isRawType() {
93             return true;
94         }       
95         
96         protected void initializeArguments() {
97                 TypeVariableBinding[] typeVariables = this.type.typeVariables();
98                 int length = typeVariables.length;
99                 TypeBinding[] typeArguments = new TypeBinding[length];
100                 for (int i = 0; i < length; i++) {
101                     typeArguments[i] = typeVariables[i].erasure();
102                 }
103                 this.arguments = typeArguments;
104         }
105         /**
106          * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
107          */
108         public char[] readableName() /*java.lang.Object,  p.X<T> */ {
109             char[] readableName;
110                 if (isMemberType()) {
111                         readableName = CharOperation.concat(enclosingType().readableName(), sourceName, '.');
112                 } else {
113                         readableName = CharOperation.concatWith(this.type.compoundName, '.');
114                 }
115                 return readableName;
116         }
117
118         /**
119          * Returns a type, where original type was substituted using the receiver
120          * raw type.
121          * On raw types, all parameterized type denoting same original type are converted
122          * to raw types. e.g. 
123          * class X <T> {
124          *   X<T> foo;
125          *   X<String> bar;
126          * } when used in raw fashion, then type of both foo and bar is raw type X.
127          */
128         public TypeBinding substitute(TypeBinding originalType) {
129             
130                 switch (originalType.kind()) {
131                         
132                         case Binding.TYPE_PARAMETER:
133                         TypeVariableBinding originalVariable = (TypeVariableBinding) originalType;
134                             ParameterizedTypeBinding currentType = this;
135                         while (true) {
136                                 TypeVariableBinding[] typeVariables = currentType.type.typeVariables();
137                                 int length = typeVariables.length;
138                                 // check this variable can be substituted given parameterized type
139                                 if (originalVariable.rank < length && typeVariables[originalVariable.rank] == originalVariable) {
140                                             // lazy init, since cannot do so during binding creation if during supertype connection
141                                             if (currentType.arguments == null)  currentType.initializeArguments();
142                                             if (currentType.arguments != null)
143                                            return currentType.arguments[originalVariable.rank];
144                                 }
145                                     // recurse on enclosing type, as it may hold more substitutions to perform
146                                     ReferenceBinding enclosing = currentType.enclosingType();
147                                     if (!(enclosing instanceof ParameterizedTypeBinding))
148                                         break;
149                                     currentType = (ParameterizedTypeBinding) enclosing;
150                         }
151                         break;
152                         
153                         case Binding.PARAMETERIZED_TYPE:
154                                 ReferenceBinding substitutedEnclosing = originalType.enclosingType();
155                                 if (substitutedEnclosing != null) {
156                                         substitutedEnclosing = (ReferenceBinding) this.substitute(substitutedEnclosing);
157                                 }                               
158                         ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
159                                 return this.environment.createRawType(originalParameterizedType.type, substitutedEnclosing);
160                                 
161                         case Binding.GENERIC_TYPE:
162                                 substitutedEnclosing = originalType.enclosingType();
163                                 if (substitutedEnclosing != null) {
164                                         substitutedEnclosing = (ReferenceBinding) this.substitute(substitutedEnclosing);
165                                 }                               
166                     return this.environment.createRawType((ReferenceBinding)originalType, substitutedEnclosing);
167                     
168                         case Binding.WILDCARD_TYPE:
169                         WildcardBinding wildcard = (WildcardBinding) originalType;
170                         if (wildcard.kind != Wildcard.UNBOUND) {
171                                 TypeBinding originalBound = wildcard.bound;
172                                 TypeBinding substitutedBound = substitute(originalBound);
173                                 if (substitutedBound != originalBound) {
174                                         return this.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, wildcard.kind);
175                                 }
176                         }
177                         break;
178                         
179                         case Binding.ARRAY_TYPE:
180                                 TypeBinding originalLeafComponentType = originalType.leafComponentType();
181                                 TypeBinding substitute = substitute(originalLeafComponentType); // substitute could itself be array type
182                                 if (substitute != originalLeafComponentType) {
183                                         return this.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
184                                 }
185                                 break;
186             }
187             return originalType;
188         }       
189
190         /**
191          * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
192          */
193         public char[] shortReadableName() /*Object*/ {
194             char[] shortReadableName;
195                 if (isMemberType()) {
196                         shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
197                 } else {
198                         shortReadableName = this.type.sourceName;
199                 }
200                 return shortReadableName;
201         }
202 }