/******************************************************************************* * Copyright (c) 2000, 2007 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 * *******************************************************************************/ package org.eclipse.dltk.internal.core.search.matching; import java.io.IOException; import org.eclipse.dltk.compiler.CharOperation; import org.eclipse.dltk.core.IDLTKLanguageToolkit; import org.eclipse.dltk.core.search.SearchPattern; import org.eclipse.dltk.core.search.index.EntryResult; import org.eclipse.dltk.core.search.index.Index; import org.eclipse.dltk.core.search.indexing.IIndexConstants; public class SuperTypeReferencePattern extends DLTKSearchPattern { 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 = { IIndexConstants.SUPER_REF }; public static char[] createIndexKey(int modifiers, String namespace[], String typeName, String[] enclosingTypeNames, char[][] typeParameterSignatures, char classOrInterface, char[] superTypeName, char superClassOrInterface) { if (superTypeName == null) superTypeName = "(base object)".toCharArray(); //$NON-NLS-1$ 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; } String simpleName = CharOperation.lastSegment(typeName, '.'); char[] enclosingTypeName = CharOperation.concatWith(enclosingTypeNames, '$'); if (superQualification != null && CharOperation.equals(superQualification, CharOperation.concatWith(namespace, '$'))) namespace = IIndexConstants.ONE_ZERO_CHAR_STRINGS; // 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 = indexKeyLength(namespace); 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++] = IIndexConstants.SEPARATOR; if (superQLength > 0) { System.arraycopy(superQualification, 0, result, pos, superQLength); pos += superQLength; } result[pos++] = IIndexConstants.SEPARATOR; if (simpleLength > 0) { simpleName.getChars(0, simpleLength, result, pos); pos += simpleLength; } result[pos++] = IIndexConstants.SEPARATOR; if (enclosingLength > 0) { System.arraycopy(enclosingTypeName, 0, result, pos, enclosingLength); pos += enclosingLength; } result[pos++] = IIndexConstants.SEPARATOR; if (typeParametersLength > 0) { System.arraycopy(typeParameters, 0, result, pos, typeParametersLength); pos += typeParametersLength; } result[pos++] = IIndexConstants.SEPARATOR; if (packageLength > 0) { pos = encodeNames(namespace, packageLength, result, pos); } result[pos++] = IIndexConstants.SEPARATOR; result[pos++] = superClassOrInterface; result[pos++] = classOrInterface; result[pos] = (char) modifiers; return result; } public SuperTypeReferencePattern(char[] superQualification, char[] superSimpleName, int superRefKind, int matchRule, IDLTKLanguageToolkit toolkit) { this(matchRule, toolkit); this.superQualification = isCaseSensitive() ? superQualification : CharOperation.toLowerCase(superQualification); this.superSimpleName = (isCaseSensitive() || isCamelCase()) ? superSimpleName : CharOperation.toLowerCase(superSimpleName); // ((InternalSearchPattern) this).mustResolve = superQualification != // null; this.superRefKind = superRefKind; } public SuperTypeReferencePattern(char[] superQualification, char[] superSimpleName, int superRefKind, char typeSuffix, int matchRule, IDLTKLanguageToolkit toolkit) { this(superQualification, superSimpleName, superRefKind, matchRule, toolkit); this.typeSuffix = typeSuffix; // ((InternalSearchPattern) this).mustResolve = superQualification != // null // || typeSuffix != TYPE_SUFFIX; } SuperTypeReferencePattern(int matchRule, IDLTKLanguageToolkit toolkit) { super(IIndexConstants.SUPER_REF_PATTERN, matchRule, toolkit); } /* * superSimpleName / superQualification / simpleName / enclosingTypeName / * typeParameters / pkgName / superClassOrInterface classOrInterface * modifiers */ public void decodeIndexKey(char[] key) { int slash = CharOperation.indexOf(IIndexConstants.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(IIndexConstants.SEPARATOR, key, start); this.superQualification = slash == start ? null : CharOperation .subarray(key, start, slash); slash = CharOperation.indexOf(IIndexConstants.SEPARATOR, key, start = slash + 1); this.simpleName = CharOperation.subarray(key, start, slash); start = ++slash; if (key[start] == IIndexConstants.SEPARATOR) { this.enclosingTypeName = null; } else { slash = CharOperation .indexOf(IIndexConstants.SEPARATOR, key, start); if (slash == (start + 1) && key[start] == IIndexConstants.ZERO_CHAR) { this.enclosingTypeName = IIndexConstants.ONE_ZERO; } else { char[] names = CharOperation.subarray(key, start, slash); this.enclosingTypeName = names; } } start = ++slash; if (key[start] == IIndexConstants.SEPARATOR) { this.typeParameterSignatures = null; } else { slash = CharOperation .indexOf(IIndexConstants.SEPARATOR, key, start); this.typeParameterSignatures = CharOperation.splitOn(',', key, start, slash); } start = ++slash; if (key[start] == IIndexConstants.SEPARATOR) { this.pkgName = null; } else { slash = CharOperation .indexOf(IIndexConstants.SEPARATOR, key, start); if (slash == (start + 1) && key[start] == IIndexConstants.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, getToolkit()); } public char[][] getIndexCategories() { return CATEGORIES; } public boolean matchesDecodedKey(SearchPattern decodedPattern) { SuperTypeReferencePattern pattern = (SuperTypeReferencePattern) decodedPattern; if (this.superRefKind == ONLY_SUPER_CLASSES && pattern.enclosingTypeName != IIndexConstants.ONE_ZERO/* * not * an * anonymous */) // consider enumerations as classes, reject interfaces and // annotations if (pattern.superClassOrInterface == IIndexConstants.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: if (this.isCamelCase) break; // do a prefix query with the superSimpleName matchRule &= ~R_EXACT_MATCH; matchRule |= R_PREFIX_MATCH; if (this.superSimpleName != null) key = CharOperation.append(this.superSimpleName, IIndexConstants.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; } 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 (superSimpleName != null) output.append(superSimpleName); else output.append("*"); //$NON-NLS-1$ output.append(">"); //$NON-NLS-1$ return super.print(output); } }