001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.core.search.matching;
011:
012: import java.io.IOException;
013:
014: import org.eclipse.jdt.core.compiler.*;
015: import org.eclipse.jdt.core.search.*;
016: import org.eclipse.jdt.internal.core.index.*;
017:
018: public class SuperTypeReferencePattern extends JavaSearchPattern {
019:
020: public char[] super Qualification;
021: public char[] super SimpleName;
022: public char super ClassOrInterface;
023:
024: // set to CLASS_SUFFIX for only matching classes
025: // set to INTERFACE_SUFFIX for only matching interfaces
026: // set to TYPE_SUFFIX for matching both classes and interfaces
027: public char typeSuffix;
028: public char[] pkgName;
029: public char[] simpleName;
030: public char[] enclosingTypeName;
031: public char classOrInterface;
032: public int modifiers;
033: public char[][] typeParameterSignatures;
034:
035: protected int super RefKind;
036: public static final int ALL_SUPER_TYPES = 0;
037: public static final int ONLY_SUPER_INTERFACES = 1; // used for IMPLEMENTORS
038: public static final int ONLY_SUPER_CLASSES = 2; // used for hierarchy with a class focus
039:
040: protected static char[][] CATEGORIES = { SUPER_REF };
041:
042: public static char[] createIndexKey(int modifiers,
043: char[] packageName, char[] typeName,
044: char[][] enclosingTypeNames,
045: char[][] typeParameterSignatures, char classOrInterface,
046: char[] super TypeName, char super ClassOrInterface) {
047:
048: if (super TypeName == null)
049: super TypeName = OBJECT;
050: char[] super SimpleName = CharOperation.lastSegment(
051: super TypeName, '.');
052: char[] super Qualification = null;
053: if (super SimpleName != super TypeName) {
054: int length = super TypeName.length - super SimpleName.length
055: - 1;
056: super Qualification = new char[length];
057: System.arraycopy(super TypeName, 0, super Qualification, 0,
058: length);
059: }
060:
061: // if the supertype name contains a $, then split it into: source name and append the $ prefix to the qualification
062: // e.g. p.A$B ---> p.A$ + B
063: char[] super TypeSourceName = CharOperation.lastSegment(
064: super SimpleName, '$');
065: if (super TypeSourceName != super SimpleName) {
066: int start = super Qualification == null ? 0
067: : super Qualification.length + 1;
068: int prefixLength = super SimpleName.length
069: - super TypeSourceName.length;
070: char[] mangledQualification = new char[start + prefixLength];
071: if (super Qualification != null) {
072: System.arraycopy(super Qualification, 0,
073: mangledQualification, 0, start - 1);
074: mangledQualification[start - 1] = '.';
075: }
076: System.arraycopy(super SimpleName, 0, mangledQualification,
077: start, prefixLength);
078: super Qualification = mangledQualification;
079: super SimpleName = super TypeSourceName;
080: }
081:
082: char[] simpleName = CharOperation.lastSegment(typeName, '.');
083: char[] enclosingTypeName = CharOperation.concatWith(
084: enclosingTypeNames, '$');
085: if (super Qualification != null
086: && CharOperation
087: .equals(super Qualification, packageName))
088: packageName = ONE_ZERO; // save some space
089:
090: char[] typeParameters = CharOperation.NO_CHAR;
091: int typeParametersLength = 0;
092: if (typeParameterSignatures != null) {
093: StringBuffer buffer = new StringBuffer();
094: for (int i = 0, length = typeParameterSignatures.length; i < length; i++) {
095: char[] typeParameter = typeParameterSignatures[i];
096: buffer.append(typeParameter);
097: typeParametersLength += typeParameter.length;
098: if (i != length - 1) {
099: buffer.append(',');
100: typeParametersLength++;
101: }
102: }
103: typeParameters = new char[typeParametersLength];
104: buffer.getChars(0, typeParametersLength, typeParameters, 0);
105: }
106:
107: // superSimpleName / superQualification / simpleName / enclosingTypeName / typeParameters / packageName / superClassOrInterface classOrInterface modifiers
108: int super Length = super SimpleName == null ? 0
109: : super SimpleName.length;
110: int super QLength = super Qualification == null ? 0
111: : super Qualification.length;
112: int simpleLength = simpleName == null ? 0 : simpleName.length;
113: int enclosingLength = enclosingTypeName == null ? 0
114: : enclosingTypeName.length;
115: int packageLength = packageName == null ? 0
116: : packageName.length;
117: char[] result = new char[super Length + super QLength
118: + simpleLength + enclosingLength + typeParametersLength
119: + packageLength + 9];
120: int pos = 0;
121: if (super Length > 0) {
122: System.arraycopy(super SimpleName, 0, result, pos,
123: super Length);
124: pos += super Length;
125: }
126: result[pos++] = SEPARATOR;
127: if (super QLength > 0) {
128: System.arraycopy(super Qualification, 0, result, pos,
129: super QLength);
130: pos += super QLength;
131: }
132: result[pos++] = SEPARATOR;
133: if (simpleLength > 0) {
134: System.arraycopy(simpleName, 0, result, pos, simpleLength);
135: pos += simpleLength;
136: }
137: result[pos++] = SEPARATOR;
138: if (enclosingLength > 0) {
139: System.arraycopy(enclosingTypeName, 0, result, pos,
140: enclosingLength);
141: pos += enclosingLength;
142: }
143: result[pos++] = SEPARATOR;
144: if (typeParametersLength > 0) {
145: System.arraycopy(typeParameters, 0, result, pos,
146: typeParametersLength);
147: pos += typeParametersLength;
148: }
149: result[pos++] = SEPARATOR;
150: if (packageLength > 0) {
151: System
152: .arraycopy(packageName, 0, result, pos,
153: packageLength);
154: pos += packageLength;
155: }
156: result[pos++] = SEPARATOR;
157: result[pos++] = super ClassOrInterface;
158: result[pos++] = classOrInterface;
159: result[pos] = (char) modifiers;
160: return result;
161: }
162:
163: public SuperTypeReferencePattern(char[] super Qualification,
164: char[] super SimpleName, int super RefKind, int matchRule) {
165:
166: this (matchRule);
167:
168: this .super Qualification = this .isCaseSensitive ? super Qualification
169: : CharOperation.toLowerCase(super Qualification);
170: this .super SimpleName = (this .isCaseSensitive || this .isCamelCase) ? super SimpleName
171: : CharOperation.toLowerCase(super SimpleName);
172: ((InternalSearchPattern) this ).mustResolve = super Qualification != null;
173: this .super RefKind = super RefKind;
174: }
175:
176: public SuperTypeReferencePattern(char[] super Qualification,
177: char[] super SimpleName, int super RefKind, char typeSuffix,
178: int matchRule) {
179:
180: this (super Qualification, super SimpleName, super RefKind,
181: matchRule);
182: this .typeSuffix = typeSuffix;
183: ((InternalSearchPattern) this ).mustResolve = super Qualification != null
184: || typeSuffix != TYPE_SUFFIX;
185: }
186:
187: SuperTypeReferencePattern(int matchRule) {
188: super (SUPER_REF_PATTERN, matchRule);
189: }
190:
191: /*
192: * superSimpleName / superQualification / simpleName / enclosingTypeName / typeParameters / pkgName / superClassOrInterface classOrInterface modifiers
193: */
194: public void decodeIndexKey(char[] key) {
195: int slash = CharOperation.indexOf(SEPARATOR, key, 0);
196: this .super SimpleName = CharOperation.subarray(key, 0, slash);
197:
198: // some values may not have been know when indexed so decode as null
199: int start = slash + 1;
200: slash = CharOperation.indexOf(SEPARATOR, key, start);
201: this .super Qualification = slash == start ? null : CharOperation
202: .subarray(key, start, slash);
203:
204: slash = CharOperation
205: .indexOf(SEPARATOR, key, start = slash + 1);
206: this .simpleName = CharOperation.subarray(key, start, slash);
207:
208: start = ++slash;
209: if (key[start] == SEPARATOR) {
210: this .enclosingTypeName = null;
211: } else {
212: slash = CharOperation.indexOf(SEPARATOR, key, start);
213: if (slash == (start + 1) && key[start] == ZERO_CHAR) {
214: this .enclosingTypeName = ONE_ZERO;
215: } else {
216: char[] names = CharOperation
217: .subarray(key, start, slash);
218: this .enclosingTypeName = names;
219: }
220: }
221:
222: start = ++slash;
223: if (key[start] == SEPARATOR) {
224: this .typeParameterSignatures = null;
225: } else {
226: slash = CharOperation.indexOf(SEPARATOR, key, start);
227: this .typeParameterSignatures = CharOperation.splitOn(',',
228: key, start, slash);
229: }
230:
231: start = ++slash;
232: if (key[start] == SEPARATOR) {
233: this .pkgName = null;
234: } else {
235: slash = CharOperation.indexOf(SEPARATOR, key, start);
236: if (slash == (start + 1) && key[start] == ZERO_CHAR) {
237: this .pkgName = this .super Qualification;
238: } else {
239: char[] names = CharOperation
240: .subarray(key, start, slash);
241: this .pkgName = names;
242: }
243: }
244:
245: this .super ClassOrInterface = key[slash + 1];
246: this .classOrInterface = key[slash + 2];
247: this .modifiers = key[slash + 3]; // implicit cast to int type
248: }
249:
250: public SearchPattern getBlankPattern() {
251: return new SuperTypeReferencePattern(R_EXACT_MATCH
252: | R_CASE_SENSITIVE);
253: }
254:
255: public char[][] getIndexCategories() {
256: return CATEGORIES;
257: }
258:
259: public boolean matchesDecodedKey(SearchPattern decodedPattern) {
260: SuperTypeReferencePattern pattern = (SuperTypeReferencePattern) decodedPattern;
261: if (this .super RefKind == ONLY_SUPER_CLASSES
262: && pattern.enclosingTypeName != ONE_ZERO/*not an anonymous*/)
263: // consider enumerations as classes, reject interfaces and annotations
264: if (pattern.super ClassOrInterface == INTERFACE_SUFFIX
265: || pattern.super ClassOrInterface == ANNOTATION_TYPE_SUFFIX)
266: return false;
267:
268: if (pattern.super Qualification != null)
269: if (!matchesName(this .super Qualification,
270: pattern.super Qualification))
271: return false;
272:
273: return matchesName(this .super SimpleName,
274: pattern.super SimpleName);
275: }
276:
277: EntryResult[] queryIn(Index index) throws IOException {
278: char[] key = this .super SimpleName; // can be null
279: int matchRule = getMatchRule();
280:
281: // cannot include the superQualification since it may not exist in the index
282: switch (getMatchMode()) {
283: case R_EXACT_MATCH:
284: if (this .isCamelCase)
285: break;
286: // do a prefix query with the superSimpleName
287: matchRule &= ~R_EXACT_MATCH;
288: matchRule |= R_PREFIX_MATCH;
289: if (this .super SimpleName != null)
290: key = CharOperation.append(this .super SimpleName,
291: SEPARATOR);
292: break;
293: case R_PREFIX_MATCH:
294: // do a prefix query with the superSimpleName
295: break;
296: case R_PATTERN_MATCH:
297: // do a pattern query with the superSimpleName
298: break;
299: case R_REGEXP_MATCH:
300: // TODO (frederic) implement regular expression match
301: break;
302: }
303:
304: return index.query(getIndexCategories(), key, matchRule); // match rule is irrelevant when the key is null
305: }
306:
307: protected StringBuffer print(StringBuffer output) {
308: switch (this .super RefKind) {
309: case ALL_SUPER_TYPES:
310: output.append("SuperTypeReferencePattern: <"); //$NON-NLS-1$
311: break;
312: case ONLY_SUPER_INTERFACES:
313: output.append("SuperInterfaceReferencePattern: <"); //$NON-NLS-1$
314: break;
315: case ONLY_SUPER_CLASSES:
316: output.append("SuperClassReferencePattern: <"); //$NON-NLS-1$
317: break;
318: }
319: if (super SimpleName != null)
320: output.append(super SimpleName);
321: else
322: output.append("*"); //$NON-NLS-1$
323: output.append(">"); //$NON-NLS-1$
324: return super.print(output);
325: }
326: }
|