1 11 package org.eclipse.jdt.internal.core.search.matching; 12 13 import java.io.IOException ; 14 15 import org.eclipse.jdt.core.compiler.CharOperation; 16 import org.eclipse.jdt.core.search.SearchPattern; 17 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 18 import org.eclipse.jdt.internal.core.index.*; 19 20 public class TypeDeclarationPattern extends JavaSearchPattern { 21 22 public char[] simpleName; 23 public char[] pkg; 24 public char[][] enclosingTypeNames; 25 26 public char typeSuffix; 32 public int modifiers; 33 public boolean secondary = false; 34 35 protected static char[][] CATEGORIES = { TYPE_DECL }; 36 37 static PackageNameSet internedPackageNames = new PackageNameSet(1001); 39 static class PackageNameSet { 40 41 public char[][] names; 42 public int elementSize; public int threshold; 44 45 PackageNameSet(int size) { 46 this.elementSize = 0; 47 this.threshold = size; int extraRoom = (int) (size * 1.5f); 49 if (this.threshold == extraRoom) 50 extraRoom++; 51 this.names = new char[extraRoom][]; 52 } 53 54 char[] add(char[] name) { 55 int length = names.length; 56 int index = CharOperation.hashCode(name) % length; 57 char[] current; 58 while ((current = names[index]) != null) { 59 if (CharOperation.equals(current, name)) return current; 60 if (++index == length) index = 0; 61 } 62 names[index] = name; 63 64 if (++elementSize > threshold) rehash(); 66 return name; 67 } 68 69 void rehash() { 70 PackageNameSet newSet = new PackageNameSet(elementSize * 2); char[] current; 72 for (int i = names.length; --i >= 0;) 73 if ((current = names[i]) != null) 74 newSet.add(current); 75 76 this.names = newSet.names; 77 this.elementSize = newSet.elementSize; 78 this.threshold = newSet.threshold; 79 } 80 } 81 82 88 public static char[] createIndexKey(int modifiers, char[] typeName, char[] packageName, char[][] enclosingTypeNames, boolean secondary) { int typeNameLength = typeName == null ? 0 : typeName.length; 90 int packageLength = packageName == null ? 0 : packageName.length; 91 int enclosingNamesLength = 0; 92 if (enclosingTypeNames != null) { 93 for (int i = 0, length = enclosingTypeNames.length; i < length;) { 94 enclosingNamesLength += enclosingTypeNames[i].length; 95 if (++i < length) 96 enclosingNamesLength++; } 98 } 99 100 int resultLength = typeNameLength + packageLength + enclosingNamesLength + 5; 101 if (secondary) resultLength += 2; 102 char[] result = new char[resultLength]; 103 int pos = 0; 104 if (typeNameLength > 0) { 105 System.arraycopy(typeName, 0, result, pos, typeNameLength); 106 pos += typeNameLength; 107 } 108 result[pos++] = SEPARATOR; 109 if (packageLength > 0) { 110 System.arraycopy(packageName, 0, result, pos, packageLength); 111 pos += packageLength; 112 } 113 result[pos++] = SEPARATOR; 114 if (enclosingTypeNames != null && enclosingNamesLength > 0) { 115 for (int i = 0, length = enclosingTypeNames.length; i < length;) { 116 char[] enclosingName = enclosingTypeNames[i]; 117 int itsLength = enclosingName.length; 118 System.arraycopy(enclosingName, 0, result, pos, itsLength); 119 pos += itsLength; 120 if (++i < length) 121 result[pos++] = '.'; 122 } 123 } 124 result[pos++] = SEPARATOR; 125 result[pos++] = (char) modifiers; 126 result[pos] = (char) (modifiers>>16); 127 if (secondary) { 128 result[++pos] = SEPARATOR; 129 result[++pos] = 'S'; 130 } 131 return result; 132 } 133 134 public TypeDeclarationPattern( 135 char[] pkg, 136 char[][] enclosingTypeNames, 137 char[] simpleName, 138 char typeSuffix, 139 int matchRule) { 140 141 this(matchRule); 142 143 this.pkg = isCaseSensitive() ? pkg : CharOperation.toLowerCase(pkg); 144 if (isCaseSensitive() || enclosingTypeNames == null) { 145 this.enclosingTypeNames = enclosingTypeNames; 146 } else { 147 int length = enclosingTypeNames.length; 148 this.enclosingTypeNames = new char[length][]; 149 for (int i = 0; i < length; i++) 150 this.enclosingTypeNames[i] = CharOperation.toLowerCase(enclosingTypeNames[i]); 151 } 152 this.simpleName = (isCaseSensitive() || isCamelCase()) ? simpleName : CharOperation.toLowerCase(simpleName); 153 this.typeSuffix = typeSuffix; 154 155 ((InternalSearchPattern)this).mustResolve = (this.pkg != null && this.enclosingTypeNames != null) || typeSuffix != TYPE_SUFFIX; 156 } 157 TypeDeclarationPattern(int matchRule) { 158 super(TYPE_DECL_PATTERN, matchRule); 159 } 160 169 public void decodeIndexKey(char[] key) { 170 int slash = CharOperation.indexOf(SEPARATOR, key, 0); 171 this.simpleName = CharOperation.subarray(key, 0, slash); 172 173 int start = ++slash; 174 if (key[start] == SEPARATOR) { 175 this.pkg = CharOperation.NO_CHAR; 176 } else { 177 slash = CharOperation.indexOf(SEPARATOR, key, start); 178 this.pkg = internedPackageNames.add(CharOperation.subarray(key, start, slash)); 179 } 180 181 int last = key.length-1; 183 this.secondary = key[last] == 'S'; 184 if (this.secondary) { 185 last -= 2; 186 } 187 this.modifiers = key[last-1] + (key[last]<<16); 188 decodeModifiers(); 189 190 start = slash + 1; 192 last -= 2; if (start == last) { 194 this.enclosingTypeNames = CharOperation.NO_CHAR_CHAR; 195 } else { 196 if (last == (start+1) && key[start] == ZERO_CHAR) { 197 this.enclosingTypeNames = ONE_ZERO_CHAR; 198 } else { 199 this.enclosingTypeNames = CharOperation.splitOn('.', key, start, last); 200 } 201 } 202 } 203 protected void decodeModifiers() { 204 205 switch (this.modifiers & (ClassFileConstants.AccInterface|ClassFileConstants.AccEnum|ClassFileConstants.AccAnnotation)) { 207 case ClassFileConstants.AccAnnotation: 208 case ClassFileConstants.AccAnnotation+ClassFileConstants.AccInterface: 209 this.typeSuffix = ANNOTATION_TYPE_SUFFIX; 210 break; 211 case ClassFileConstants.AccEnum: 212 this.typeSuffix = ENUM_SUFFIX; 213 break; 214 case ClassFileConstants.AccInterface: 215 this.typeSuffix = INTERFACE_SUFFIX; 216 break; 217 default: 218 this.typeSuffix = CLASS_SUFFIX; 219 break; 220 } 221 } 222 public SearchPattern getBlankPattern() { 223 return new TypeDeclarationPattern(R_EXACT_MATCH | R_CASE_SENSITIVE); 224 } 225 public char[][] getIndexCategories() { 226 return CATEGORIES; 227 } 228 public boolean matchesDecodedKey(SearchPattern decodedPattern) { 229 TypeDeclarationPattern pattern = (TypeDeclarationPattern) decodedPattern; 230 231 if (this.typeSuffix != pattern.typeSuffix && typeSuffix != TYPE_SUFFIX) { 233 if (!matchDifferentTypeSuffixes(this.typeSuffix, pattern.typeSuffix)) { 234 return false; 235 } 236 } 237 238 if (!matchesName(this.simpleName, pattern.simpleName)) 240 return false; 241 242 if (this.pkg != null && !CharOperation.equals(this.pkg, pattern.pkg, isCaseSensitive())) 244 return false; 245 246 if (this.enclosingTypeNames != null) { 248 if (this.enclosingTypeNames.length == 0) 249 return pattern.enclosingTypeNames.length == 0; 250 if (this.enclosingTypeNames.length == 1 && pattern.enclosingTypeNames.length == 1) 251 return CharOperation.equals(this.enclosingTypeNames[0], pattern.enclosingTypeNames[0], isCaseSensitive()); 252 if (pattern.enclosingTypeNames == ONE_ZERO_CHAR) 253 return true; return CharOperation.equals(this.enclosingTypeNames, pattern.enclosingTypeNames, isCaseSensitive()); 255 } 256 return true; 257 } 258 EntryResult[] queryIn(Index index) throws IOException { 259 char[] key = this.simpleName; int matchRule = getMatchRule(); 261 262 switch(getMatchMode()) { 263 case R_PREFIX_MATCH : 264 break; 266 case R_EXACT_MATCH : 267 if (this.isCamelCase) break; 268 matchRule &= ~R_EXACT_MATCH; 269 if (this.simpleName != null) { 270 matchRule |= R_PREFIX_MATCH; 271 key = this.pkg == null 272 ? CharOperation.append(this.simpleName, SEPARATOR) 273 : CharOperation.concat(this.simpleName, SEPARATOR, this.pkg, SEPARATOR, CharOperation.NO_CHAR); 274 break; } 276 matchRule |= R_PATTERN_MATCH; 277 case R_PATTERN_MATCH : 279 if (this.pkg == null) { 280 if (this.simpleName == null) { 281 switch(this.typeSuffix) { 282 case CLASS_SUFFIX : 283 case INTERFACE_SUFFIX : 284 case ENUM_SUFFIX : 285 case ANNOTATION_TYPE_SUFFIX : 286 case CLASS_AND_INTERFACE_SUFFIX : 287 case CLASS_AND_ENUM_SUFFIX : 288 case INTERFACE_AND_ANNOTATION_SUFFIX : 289 break; 292 } 293 } else if (this.simpleName[this.simpleName.length - 1] != '*') { 294 key = CharOperation.concat(this.simpleName, ONE_STAR, SEPARATOR); 295 } 296 break; } 298 key = CharOperation.concat( 300 this.simpleName == null ? ONE_STAR : this.simpleName, SEPARATOR, this.pkg, SEPARATOR, ONE_STAR); 301 break; 302 case R_REGEXP_MATCH : 303 break; 305 } 306 307 return index.query(getIndexCategories(), key, matchRule); } 309 protected StringBuffer print(StringBuffer output) { 310 switch (this.typeSuffix){ 311 case CLASS_SUFFIX : 312 output.append("ClassDeclarationPattern: pkg<"); break; 314 case CLASS_AND_INTERFACE_SUFFIX: 315 output.append("ClassAndInterfaceDeclarationPattern: pkg<"); break; 317 case CLASS_AND_ENUM_SUFFIX : 318 output.append("ClassAndEnumDeclarationPattern: pkg<"); break; 320 case INTERFACE_SUFFIX : 321 output.append("InterfaceDeclarationPattern: pkg<"); break; 323 case INTERFACE_AND_ANNOTATION_SUFFIX: 324 output.append("InterfaceAndAnnotationDeclarationPattern: pkg<"); break; 326 case ENUM_SUFFIX : 327 output.append("EnumDeclarationPattern: pkg<"); break; 329 case ANNOTATION_TYPE_SUFFIX : 330 output.append("AnnotationTypeDeclarationPattern: pkg<"); break; 332 default : 333 output.append("TypeDeclarationPattern: pkg<"); break; 335 } 336 if (pkg != null) 337 output.append(pkg); 338 else 339 output.append("*"); output.append(">, enclosing<"); if (enclosingTypeNames != null) { 342 for (int i = 0; i < enclosingTypeNames.length; i++){ 343 output.append(enclosingTypeNames[i]); 344 if (i < enclosingTypeNames.length - 1) 345 output.append('.'); 346 } 347 } else { 348 output.append("*"); } 350 output.append(">, type<"); if (simpleName != null) 352 output.append(simpleName); 353 else 354 output.append("*"); output.append(">"); return super.print(output); 357 } 358 } 359 | Popular Tags |