added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / lookup / LocalTypeBinding.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.CaseStatement;
15 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
16
17 public final class LocalTypeBinding extends NestedTypeBinding {
18         final static char[] LocalTypePrefix = { '$', 'L', 'o', 'c', 'a', 'l', '$' };
19
20         private InnerEmulationDependency[] dependents;
21         public ArrayBinding[] localArrayBindings; // used to cache array bindings of various dimensions for this local type
22         public CaseStatement switchCase; // from 1.4 on, local types should not be accessed across switch case blocks (52221)
23         
24 public LocalTypeBinding(ClassScope scope, SourceTypeBinding enclosingType, CaseStatement switchCase) {
25         super(
26                 new char[][] {CharOperation.concat(LocalTypePrefix, scope.referenceContext.name)},
27                 scope,
28                 enclosingType);
29         
30         if (this.sourceName == TypeDeclaration.ANONYMOUS_EMPTY_NAME)
31                 this.tagBits |= AnonymousTypeMask;
32         else
33                 this.tagBits |= LocalTypeMask;
34         this.switchCase = switchCase;
35 }
36 /* Record a dependency onto a source target type which may be altered
37 * by the end of the innerclass emulation. Later on, we will revisit
38 * all its dependents so as to update them (see updateInnerEmulationDependents()).
39 */
40
41 public void addInnerEmulationDependent(BlockScope dependentScope, boolean wasEnclosingInstanceSupplied) {
42         int index;
43         if (dependents == null) {
44                 index = 0;
45                 dependents = new InnerEmulationDependency[1];
46         } else {
47                 index = dependents.length;
48                 for (int i = 0; i < index; i++)
49                         if (dependents[i].scope == dependentScope)
50                                 return; // already stored
51                 System.arraycopy(dependents, 0, (dependents = new InnerEmulationDependency[index + 1]), 0, index);
52         }
53         dependents[index] = new InnerEmulationDependency(dependentScope, wasEnclosingInstanceSupplied);
54         //  System.out.println("Adding dependency: "+ new String(scope.enclosingType().readableName()) + " --> " + new String(this.readableName()));
55 }
56 /* Answer the receiver's constant pool name.
57 *
58 * NOTE: This method should only be used during/after code gen.
59 */
60
61 public char[] constantPoolName() /* java/lang/Object */ {
62         return constantPoolName;
63 }
64
65 ArrayBinding createArrayType(int dimensionCount) {
66         if (localArrayBindings == null) {
67                 localArrayBindings = new ArrayBinding[] {new ArrayBinding(this, dimensionCount, scope.environment())};
68                 return localArrayBindings[0];
69         }
70
71         // find the cached array binding for this dimensionCount (if any)
72         int length = localArrayBindings.length;
73         for (int i = 0; i < length; i++)
74                 if (localArrayBindings[i].dimensions == dimensionCount)
75                         return localArrayBindings[i];
76
77         // no matching array
78         System.arraycopy(localArrayBindings, 0, localArrayBindings = new ArrayBinding[length + 1], 0, length); 
79         return localArrayBindings[length] = new ArrayBinding(this, dimensionCount, scope.environment());
80 }
81
82 public char[] readableName() /*java.lang.Object,  p.X<T> */ {
83     char[] readableName;
84         if (isAnonymousType()) {
85                 if (superInterfaces == NoSuperInterfaces)
86                         readableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.readableName(), TypeConstants.ANONYM_SUFFIX);
87                 else
88                         readableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].readableName(), TypeConstants.ANONYM_SUFFIX);
89         } else if (isMemberType()) {
90                 readableName = CharOperation.concat(enclosingType().readableName(), this.sourceName, '.');
91         } else {
92                 readableName = this.sourceName;
93         }    
94         TypeVariableBinding[] typeVars;
95         if ((typeVars = this.typeVariables()) != NoTypeVariables) {
96             StringBuffer nameBuffer = new StringBuffer(10);
97             nameBuffer.append(readableName).append('<');
98             for (int i = 0, length = typeVars.length; i < length; i++) {
99                 if (i > 0) nameBuffer.append(',');
100                 nameBuffer.append(typeVars[i].readableName());
101             }
102             nameBuffer.append('>');
103             int nameLength = nameBuffer.length();
104                 readableName = new char[nameLength];
105                 nameBuffer.getChars(0, nameLength, readableName, 0);
106         }
107         return readableName;
108 }
109
110 public char[] shortReadableName() /*Object*/ {
111     char[] shortReadableName;
112         if (isAnonymousType()) {
113                 if (superInterfaces == NoSuperInterfaces)
114                         shortReadableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.shortReadableName(), TypeConstants.ANONYM_SUFFIX);
115                 else
116                         shortReadableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].shortReadableName(), TypeConstants.ANONYM_SUFFIX);
117         } else if (isMemberType()) {
118                 shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
119         } else {
120                 shortReadableName = sourceName;
121         }
122         TypeVariableBinding[] typeVars;
123         if ((typeVars = this.typeVariables()) != NoTypeVariables) {
124             StringBuffer nameBuffer = new StringBuffer(10);
125             nameBuffer.append(shortReadableName).append('<');
126             for (int i = 0, length = typeVars.length; i < length; i++) {
127                 if (i > 0) nameBuffer.append(',');
128                 nameBuffer.append(typeVars[i].shortReadableName());
129             }
130             nameBuffer.append('>');
131                 int nameLength = nameBuffer.length();
132                 shortReadableName = new char[nameLength];
133                 nameBuffer.getChars(0, nameLength, shortReadableName, 0);           
134         }
135         return shortReadableName;
136 }
137
138 // Record that the type is a local member type
139 public void setAsMemberType() {
140         tagBits |= MemberTypeMask;
141 }
142
143 public void setConstantPoolName(char[] computedConstantPoolName) /* java/lang/Object */ {
144         this.constantPoolName = computedConstantPoolName;
145 }
146
147 public char[] sourceName() {
148         if (isAnonymousType()) {
149                 if (superInterfaces == NoSuperInterfaces)
150                         return CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.sourceName(), TypeConstants.ANONYM_SUFFIX);
151                 else
152                         return CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].sourceName(), TypeConstants.ANONYM_SUFFIX);
153                         
154         } else
155                 return sourceName;
156 }
157 public String toString() {
158         if (isAnonymousType())
159                 return "Anonymous type : " + super.toString(); //$NON-NLS-1$
160         if (isMemberType())
161                 return "Local member type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$
162         return "Local type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$
163 }
164 /* Trigger the dependency mechanism forcing the innerclass emulation
165 * to be propagated to all dependent source types.
166 */
167
168 public void updateInnerEmulationDependents() {
169         if (dependents != null) {
170                 for (int i = 0; i < dependents.length; i++) {
171                         InnerEmulationDependency dependency = dependents[i];
172                         // System.out.println("Updating " + new String(this.readableName()) + " --> " + new String(dependency.scope.enclosingType().readableName()));
173                         dependency.scope.propagateInnerEmulation(this, dependency.wasEnclosingInstanceSupplied);
174                 }
175         }
176 }
177 }