/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.core.search.matching; import java.io.IOException; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.core.search.*; import org.eclipse.jdt.internal.core.index.*; public class SuperTypeReferencePattern extends JavaSearchPattern { public char[] superQualification; public char[] superSimpleName; public char superClassOrInterface; // set to CLASS_SUFFIX for only matching classes // set to INTERFACE_SUFFIX for only matching interfaces // set to TYPE_SUFFIX for matching both classes and interfaces public char typeSuffix; public char[] pkgName; public char[] simpleName; public char[] enclosingTypeName; public char classOrInterface; public int modifiers; public char[][] typeParameterSignatures; protected int superRefKind; public static final int ALL_SUPER_TYPES = 0; public static final int ONLY_SUPER_INTERFACES = 1; // used for IMPLEMENTORS public static final int ONLY_SUPER_CLASSES = 2; // used for hierarchy with a class focus protected static char[][] CATEGORIES = { SUPER_REF }; public static char[] createIndexKey( int modifiers, char[] packageName, char[] typeName, char[][] enclosingTypeNames, char[][] typeParameterSignatures, char classOrInterface, char[] superTypeName, char superClassOrInterface) { if (superTypeName == null) superTypeName = OBJECT; char[] superSimpleName = CharOperation.lastSegment(superTypeName, '.'); char[] superQualification = null; if (superSimpleName != superTypeName) { int length = superTypeName.length - superSimpleName.length - 1; superQualification = new char[length]; System.arraycopy(superTypeName, 0, superQualification, 0, length); } // if the supertype name contains a $, then split it into: source name and append the $ prefix to the qualification // e.g. p.A$B ---> p.A$ + B char[] superTypeSourceName = CharOperation.lastSegment(superSimpleName, '$'); if (superTypeSourceName != superSimpleName) { int start = superQualification == null ? 0 : superQualification.length + 1; int prefixLength = superSimpleName.length - superTypeSourceName.length; char[] mangledQualification = new char[start + prefixLength]; if (superQualification != null) { System.arraycopy(superQualification, 0, mangledQualification, 0, start-1); mangledQualification[start-1] = '.'; } System.arraycopy(superSimpleName, 0, mangledQualification, start, prefixLength); superQualification = mangledQualification; superSimpleName = superTypeSourceName; } char[] simpleName = CharOperation.lastSegment(typeName, '.'); char[] enclosingTypeName = CharOperation.concatWith(enclosingTypeNames, '$'); if (superQualification != null && CharOperation.equals(superQualification, packageName)) packageName = ONE_ZERO; // save some space char[] typeParameters = CharOperation.NO_CHAR; int typeParametersLength = 0; if (typeParameterSignatures != null) { StringBuffer buffer = new StringBuffer(); for (int i = 0, length = typeParameterSignatures.length; i < length; i++) { char[] typeParameter = typeParameterSignatures[i]; buffer.append(typeParameter); typeParametersLength += typeParameter.length; if (i != length-1) { buffer.append(','); typeParametersLength++; } } typeParameters = new char[typeParametersLength]; buffer.getChars(0, typeParametersLength, typeParameters, 0); } // superSimpleName / superQualification / simpleName / enclosingTypeName / typeParameters / packageName / superClassOrInterface classOrInterface modifiers int superLength = superSimpleName == null ? 0 : superSimpleName.length; int superQLength = superQualification == null ? 0 : superQualification.length; int simpleLength = simpleName == null ? 0 : simpleName.length; int enclosingLength = enclosingTypeName == null ? 0 : enclosingTypeName.length; int packageLength = packageName == null ? 0 : packageName.length; char[] result = new char[superLength + superQLength + simpleLength + enclosingLength + typeParametersLength + packageLength + 9]; int pos = 0; if (superLength > 0) { System.arraycopy(superSimpleName, 0, result, pos, superLength); pos += superLength; } result[pos++] = SEPARATOR; if (superQLength > 0) { System.arraycopy(superQualification, 0, result, pos, superQLength); pos += superQLength; } result[pos++] = SEPARATOR; if (simpleLength > 0) { System.arraycopy(simpleName, 0, result, pos, simpleLength); pos += simpleLength; } result[pos++] = SEPARATOR; if (enclosingLength > 0) { System.arraycopy(enclosingTypeName, 0, result, pos, enclosingLength); pos += enclosingLength; } result[pos++] = SEPARATOR; if (typeParametersLength > 0) { System.arraycopy(typeParameters, 0, result, pos, typeParametersLength); pos += typeParametersLength; } result[pos++] = SEPARATOR; if (packageLength > 0) { System.arraycopy(packageName, 0, result, pos, packageLength); pos += packageLength; } result[pos++] = SEPARATOR; result[pos++] = superClassOrInterface; result[pos++] = classOrInterface; result[pos] = (char) modifiers; return result; } public SuperTypeReferencePattern( char[] superQualification, char[] superSimpleName, int superRefKind, int matchRule) { this(matchRule); this.superQualification = this.isCaseSensitive ? superQualification : CharOperation.toLowerCase(superQualification); this.superSimpleName = (this.isCaseSensitive || this.isCamelCase) ? superSimpleName : CharOperation.toLowerCase(superSimpleName); this.mustResolve = superQualification != null; this.superRefKind = superRefKind; } public SuperTypeReferencePattern( char[] superQualification, char[] superSimpleName, int superRefKind, char typeSuffix, int matchRule) { this(superQualification, superSimpleName, superRefKind, matchRule); this.typeSuffix = typeSuffix; this.mustResolve = superQualification != null || typeSuffix != TYPE_SUFFIX; } SuperTypeReferencePattern(int matchRule) { super(SUPER_REF_PATTERN, matchRule); } /* * superSimpleName / superQualification / simpleName / enclosingTypeName / typeParameters / pkgName / superClassOrInterface classOrInterface modifiers */ public void decodeIndexKey(char[] key) { int slash = CharOperation.indexOf(SEPARATOR, key, 0); this.superSimpleName = CharOperation.subarray(key, 0, slash); // some values may not have been know when indexed so decode as null int start = slash + 1; slash = CharOperation.indexOf(SEPARATOR, key, start); this.superQualification = slash == start ? null : CharOperation.subarray(key, start, slash); slash = CharOperation.indexOf(SEPARATOR, key, start = slash + 1); this.simpleName = CharOperation.subarray(key, start, slash); start = ++slash; if (key[start] == SEPARATOR) { this.enclosingTypeName = null; } else { slash = CharOperation.indexOf(SEPARATOR, key, start); if (slash == (start+1) && key[start] == ZERO_CHAR) { this.enclosingTypeName = ONE_ZERO; } else { char[] names = CharOperation.subarray(key, start, slash); this.enclosingTypeName = names; } } start = ++slash; if (key[start] == SEPARATOR) { this.typeParameterSignatures = null; } else { slash = CharOperation.indexOf(SEPARATOR, key, start); this.typeParameterSignatures = CharOperation.splitOn(',', key, start, slash); } start = ++slash; if (key[start] == SEPARATOR) { this.pkgName = null; } else { slash = CharOperation.indexOf(SEPARATOR, key, start); if (slash == (start+1) && key[start] == ZERO_CHAR) { this.pkgName = this.superQualification; } else { char[] names = CharOperation.subarray(key, start, slash); this.pkgName = names; } } this.superClassOrInterface = key[slash + 1]; this.classOrInterface = key[slash + 2]; this.modifiers = key[slash + 3]; // implicit cast to int type } public SearchPattern getBlankPattern() { return new SuperTypeReferencePattern(R_EXACT_MATCH | R_CASE_SENSITIVE); } public char[][] getIndexCategories() { return CATEGORIES; } public boolean matchesDecodedKey(SearchPattern decodedPattern) { SuperTypeReferencePattern pattern = (SuperTypeReferencePattern) decodedPattern; if (this.superRefKind == ONLY_SUPER_CLASSES && pattern.enclosingTypeName != ONE_ZERO/*not an anonymous*/) // consider enumerations as classes, reject interfaces and annotations if (pattern.superClassOrInterface == INTERFACE_SUFFIX || pattern.superClassOrInterface == ANNOTATION_TYPE_SUFFIX) return false; if (pattern.superQualification != null) if (!matchesName(this.superQualification, pattern.superQualification)) return false; return matchesName(this.superSimpleName, pattern.superSimpleName); } public EntryResult[] queryIn(Index index) throws IOException { char[] key = this.superSimpleName; // can be null int matchRule = getMatchRule(); // cannot include the superQualification since it may not exist in the index switch(getMatchMode()) { case R_EXACT_MATCH : // do a prefix query with the superSimpleName matchRule &= ~R_EXACT_MATCH; matchRule |= R_PREFIX_MATCH; if (this.superSimpleName != null) key = CharOperation.append(this.superSimpleName, SEPARATOR); break; case R_PREFIX_MATCH : // do a prefix query with the superSimpleName break; case R_PATTERN_MATCH : // do a pattern query with the superSimpleName break; case R_REGEXP_MATCH : // TODO (frederic) implement regular expression match break; case R_CAMELCASE_MATCH: case R_CAMELCASE_SAME_PART_COUNT_MATCH: // do a prefix query with the superSimpleName break; } return index.query(getIndexCategories(), key, matchRule); // match rule is irrelevant when the key is null } protected StringBuffer print(StringBuffer output) { switch (this.superRefKind) { case ALL_SUPER_TYPES: output.append("SuperTypeReferencePattern: <"); //$NON-NLS-1$ break; case ONLY_SUPER_INTERFACES: output.append("SuperInterfaceReferencePattern: <"); //$NON-NLS-1$ break; case ONLY_SUPER_CLASSES: output.append("SuperClassReferencePattern: <"); //$NON-NLS-1$ break; } if (this.superSimpleName != null) output.append(this.superSimpleName); else output.append("*"); //$NON-NLS-1$ output.append(">"); //$NON-NLS-1$ return super.print(output); } }