0691a69eac230c0eb05febed06116d79267f76e8
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / builder / ReferenceCollection.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 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 net.sourceforge.phpdt.internal.core.builder;
12
13 import java.util.ArrayList;
14
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
17
18 public class ReferenceCollection {
19
20 char[][][] qualifiedNameReferences; // contains no simple names as in just 'a' which is kept in simpleNameReferences instead
21 char[][] simpleNameReferences;
22
23 protected ReferenceCollection(char[][][] qualifiedNameReferences, char[][] simpleNameReferences) {
24         this.qualifiedNameReferences = internQualifiedNames(qualifiedNameReferences);
25         this.simpleNameReferences = internSimpleNames(simpleNameReferences, true);
26 }
27
28 boolean includes(char[] simpleName) {
29         for (int i = 0, l = simpleNameReferences.length; i < l; i++)
30                 if (simpleName == simpleNameReferences[i]) return true;
31         return false;
32 }
33
34 boolean includes(char[][] qualifiedName) {
35         for (int i = 0, l = qualifiedNameReferences.length; i < l; i++)
36                 if (qualifiedName == qualifiedNameReferences[i]) return true;
37         return false;
38 }
39
40 boolean includes(char[][][] qualifiedNames, char[][] simpleNames) {
41         // if either collection of names is null, it means it contained a well known name so we know it already has a match
42         if (simpleNames == null || qualifiedNames == null) {
43                 if (simpleNames == null && qualifiedNames == null) {
44                         if (PHPBuilder.DEBUG)
45                                 System.out.println("Found well known match"); //$NON-NLS-1$
46                         return true;
47                 } else if (qualifiedNames == null) {
48                         for (int i = 0, l = simpleNames.length; i < l; i++) {
49                                 if (includes(simpleNames[i])) {
50                                         if (PHPBuilder.DEBUG)
51                                                 System.out.println("Found match in well known package to " + new String(simpleNames[i])); //$NON-NLS-1$
52                                         return true;
53                                 }
54                         }
55                 } else {
56                         for (int i = 0, l = qualifiedNames.length; i < l; i++) {
57                                 char[][] qualifiedName = qualifiedNames[i];
58                                 if (qualifiedName.length == 1 ? includes(qualifiedName[0]) : includes(qualifiedName)) {
59                                         if (PHPBuilder.DEBUG)
60                                                 System.out.println("Found well known match in " + CharOperation.toString(qualifiedName)); //$NON-NLS-1$
61                                         return true;
62                                 }
63                         }
64                 }
65         } else {
66                 for (int i = 0, l = simpleNames.length; i < l; i++) {
67                         if (includes(simpleNames[i])) {
68                                 for (int j = 0, m = qualifiedNames.length; j < m; j++) {
69                                         char[][] qualifiedName = qualifiedNames[j];
70                                         if (qualifiedName.length == 1 ? includes(qualifiedName[0]) : includes(qualifiedName)) {
71                                                 if (PHPBuilder.DEBUG)
72                                                         System.out.println("Found match in " + CharOperation.toString(qualifiedName) //$NON-NLS-1$
73                                                                 + " to " + new String(simpleNames[i])); //$NON-NLS-1$
74                                                 return true;
75                                         }
76                                 }
77                                 return false;
78                         }
79                 }
80         }
81         return false;
82 }
83
84
85 // When any type is compiled, its methods are verified for certain problems
86 // the MethodVerifier requests 3 well known types which end up in the reference collection
87 // having WellKnownQualifiedNames & WellKnownSimpleNames, saves every type 40 bytes
88 // NOTE: These collections are sorted by length
89 static final char[][][] WellKnownQualifiedNames = new char[][][] {
90         TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION,
91         TypeConstants.JAVA_LANG_THROWABLE,
92         TypeConstants.JAVA_LANG_OBJECT,
93         TypeConstants.JAVA_LANG,
94         new char[][] {TypeConstants.JAVA},
95         new char[][] {new char[] {'o', 'r', 'g'}},
96         new char[][] {new char[] {'c', 'o', 'm'}},
97         CharOperation.NO_CHAR_CHAR}; // default package
98 static final char[][] WellKnownSimpleNames = new char[][] {
99         TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION[2],
100         TypeConstants.JAVA_LANG_THROWABLE[2],
101         TypeConstants.JAVA_LANG_OBJECT[2],
102         TypeConstants.JAVA,
103         TypeConstants.LANG,
104         new char[] {'o', 'r', 'g'},
105         new char[] {'c', 'o', 'm'}};
106
107 static final char[][][] EmptyQualifiedNames = new char[0][][];
108 static final char[][] EmptySimpleNames = CharOperation.NO_CHAR_CHAR;
109
110 // each array contains qualified char[][], one for size 2, 3, 4, 5, 6, 7 & the rest
111 static final int MaxQualifiedNames = 7;
112 static ArrayList[] InternedQualifiedNames = new ArrayList[MaxQualifiedNames];
113 // each array contains simple char[], one for size 1 to 29 & the rest
114 static final int MaxSimpleNames = 30;
115 static ArrayList[] InternedSimpleNames = new ArrayList[MaxSimpleNames];
116 static {
117         for (int i = 0; i < MaxQualifiedNames; i++)
118                 InternedQualifiedNames[i] = new ArrayList(37);
119         for (int i = 0; i < MaxSimpleNames; i++)
120                 InternedSimpleNames[i] = new ArrayList(11);
121 }
122
123 static char[][][] internQualifiedNames(ArrayList qualifiedStrings) {
124         if (qualifiedStrings == null) return EmptyQualifiedNames;
125         int length = qualifiedStrings.size();
126         if (length == 0) return EmptyQualifiedNames;
127
128         char[][][] result = new char[length][][];
129         for (int i = 0; i < length; i++)
130                 result[i] = CharOperation.splitOn('/', ((String) qualifiedStrings.get(i)).toCharArray());
131         return internQualifiedNames(result);
132 }
133
134 static char[][][] internQualifiedNames(char[][][] qualifiedNames) {
135         if (qualifiedNames == null) return EmptyQualifiedNames;
136         int length = qualifiedNames.length;
137         if (length == 0) return EmptyQualifiedNames;
138
139         char[][][] keepers = new char[length][][];
140         int index = 0;
141         next : for (int i = 0; i < length; i++) {
142                 char[][] qualifiedName = qualifiedNames[i];
143                 int qLength = qualifiedName.length;
144                 for (int j = 0, m = WellKnownQualifiedNames.length; j < m; j++) {
145                         char[][] wellKnownName = WellKnownQualifiedNames[j];
146                         if (qLength > wellKnownName.length)
147                                 break; // all remaining well known names are shorter
148                         if (CharOperation.equals(qualifiedName, wellKnownName))
149                                 continue next;
150                 }
151
152                 // InternedQualifiedNames[0] is for the rest (> 7 & 1)
153                 // InternedQualifiedNames[1] is for size 2...
154                 // InternedQualifiedNames[6] is for size 7
155                 ArrayList internedNames = InternedQualifiedNames[qLength <= MaxQualifiedNames ? qLength - 1 : 0];
156                 for (int j = 0, m = internedNames.size(); j < m; j++) {
157                         char[][] internedName = (char[][]) internedNames.get(j);
158                         if (CharOperation.equals(qualifiedName, internedName)) {
159                                 keepers[index++] = internedName;
160                                 continue next;
161                         }
162                 }
163                 qualifiedName = internSimpleNames(qualifiedName, false);
164                 internedNames.add(qualifiedName);
165                 keepers[index++] = qualifiedName;
166         }
167         if (length > index) {
168                 if (length == 0) return EmptyQualifiedNames;
169                 System.arraycopy(keepers, 0, keepers = new char[index][][], 0, index);
170         }
171         return keepers;
172 }
173
174 static char[][] internSimpleNames(ArrayList simpleStrings) {
175         if (simpleStrings == null) return EmptySimpleNames;
176         int length = simpleStrings.size();
177         if (length == 0) return EmptySimpleNames;
178
179         char[][] result = new char[length][];
180         for (int i = 0; i < length; i++)
181                 result[i] = ((String) simpleStrings.get(i)).toCharArray();
182         return internSimpleNames(result, true);
183 }
184
185 static char[][] internSimpleNames(char[][] simpleNames, boolean removeWellKnown) {
186         if (simpleNames == null) return EmptySimpleNames;
187         int length = simpleNames.length;
188         if (length == 0) return EmptySimpleNames;
189
190         char[][] keepers = new char[length][];
191         int index = 0;
192         next : for (int i = 0; i < length; i++) {
193                 char[] name = simpleNames[i];
194                 int sLength = name.length;
195                 for (int j = 0, m = WellKnownSimpleNames.length; j < m; j++) {
196                         char[] wellKnownName = WellKnownSimpleNames[j];
197                         if (sLength > wellKnownName.length)
198                                 break; // all remaining well known names are shorter
199                         if (CharOperation.equals(name, wellKnownName)) {
200                                 if (!removeWellKnown)
201                                         keepers[index++] = WellKnownSimpleNames[j];
202                                 continue next;
203                         }
204                 }
205
206                 // InternedSimpleNames[0] is for the rest (> 29)
207                 // InternedSimpleNames[1] is for size 1...
208                 // InternedSimpleNames[29] is for size 29
209                 ArrayList internedNames = InternedSimpleNames[sLength < MaxSimpleNames ? sLength : 0];
210                 for (int j = 0, m = internedNames.size(); j < m; j++) {
211                         char[] internedName = (char[]) internedNames.get(j);
212                         if (CharOperation.equals(name, internedName)) {
213                                 keepers[index++] = internedName;
214                                 continue next;
215                         }
216                 }
217                 internedNames.add(name);
218                 keepers[index++] = name;
219         }
220         if (length > index) {
221                 if (index == 0) return EmptySimpleNames;
222                 System.arraycopy(keepers, 0, keepers = new char[index][], 0, index);
223         }
224         return keepers;
225 }
226 }