001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 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 org.eclipse.jdt.core.IType;
013: import org.eclipse.jdt.core.compiler.CharOperation;
014: import org.eclipse.jdt.core.search.SearchPattern;
015: import org.eclipse.jdt.internal.core.util.Util;
016:
017: public class TypeReferencePattern extends IntersectingPattern {
018:
019: protected char[] qualification;
020: protected char[] simpleName;
021:
022: protected char[] currentCategory;
023:
024: /* Optimization: case where simpleName == null */
025: public int segmentsSize;
026: protected char[][] segments;
027: protected int currentSegment;
028:
029: protected static char[][] CATEGORIES = { REF };
030:
031: public TypeReferencePattern(char[] qualification,
032: char[] simpleName, int matchRule) {
033: this (matchRule);
034:
035: this .qualification = this .isCaseSensitive ? qualification
036: : CharOperation.toLowerCase(qualification);
037: this .simpleName = (this .isCaseSensitive || this .isCamelCase) ? simpleName
038: : CharOperation.toLowerCase(simpleName);
039:
040: if (simpleName == null)
041: this .segments = this .qualification == null ? ONE_STAR_CHAR
042: : CharOperation.splitOn('.', this .qualification);
043: else
044: this .segments = null;
045:
046: if (this .segments == null)
047: if (this .qualification == null)
048: this .segmentsSize = 0;
049: else
050: this .segmentsSize = CharOperation.occurencesOf('.',
051: this .qualification) + 1;
052: else
053: this .segmentsSize = this .segments.length;
054:
055: ((InternalSearchPattern) this ).mustResolve = true; // always resolve (in case of a simple name reference being a potential match)
056: }
057:
058: /*
059: * Instanciate a type reference pattern with additional information for generics search
060: */
061: public TypeReferencePattern(char[] qualification,
062: char[] simpleName, String typeSignature, int matchRule) {
063: this (qualification, simpleName, matchRule);
064: if (typeSignature != null) {
065: // store type signatures and arguments
066: this .typeSignatures = Util
067: .splitTypeLevelsSignature(typeSignature);
068: setTypeArguments(Util
069: .getAllTypeArguments(this .typeSignatures));
070: if (hasTypeArguments()) {
071: this .segmentsSize = getTypeArguments().length
072: + CharOperation.occurencesOf('/',
073: this .typeSignatures[0]) - 1;
074: }
075: }
076: }
077:
078: /*
079: * Instanciate a type reference pattern with additional information for generics search
080: */
081: public TypeReferencePattern(char[] qualification,
082: char[] simpleName, IType type, int matchRule) {
083: this (qualification, simpleName, matchRule);
084: storeTypeSignaturesAndArguments(type);
085: }
086:
087: TypeReferencePattern(int matchRule) {
088: super (TYPE_REF_PATTERN, matchRule);
089: }
090:
091: public void decodeIndexKey(char[] key) {
092: this .simpleName = key;
093: }
094:
095: public SearchPattern getBlankPattern() {
096: return new TypeReferencePattern(R_EXACT_MATCH
097: | R_CASE_SENSITIVE);
098: }
099:
100: public char[] getIndexKey() {
101: if (this .simpleName != null)
102: return this .simpleName;
103:
104: // Optimization, eg. type reference is 'org.eclipse.jdt.core.*'
105: if (this .currentSegment >= 0)
106: return this .segments[this .currentSegment];
107: return null;
108: }
109:
110: public char[][] getIndexCategories() {
111: return CATEGORIES;
112: }
113:
114: protected boolean hasNextQuery() {
115: if (this .segments == null)
116: return false;
117:
118: // Optimization, eg. type reference is 'org.eclipse.jdt.core.*'
119: // if package has at least 4 segments, don't look at the first 2 since they are mostly
120: // redundant (eg. in 'org.eclipse.jdt.core.*' 'org.eclipse' is used all the time)
121: return --this .currentSegment >= (this .segments.length >= 4 ? 2
122: : 0);
123: }
124:
125: public boolean matchesDecodedKey(SearchPattern decodedPattern) {
126: return true; // index key is not encoded so query results all match
127: }
128:
129: protected void resetQuery() {
130: /* walk the segments from end to start as it will find less potential references using 'lang' than 'java' */
131: if (this .segments != null)
132: this .currentSegment = this .segments.length - 1;
133: }
134:
135: protected StringBuffer print(StringBuffer output) {
136: output.append("TypeReferencePattern: qualification<"); //$NON-NLS-1$
137: if (qualification != null)
138: output.append(qualification);
139: else
140: output.append("*"); //$NON-NLS-1$
141: output.append(">, type<"); //$NON-NLS-1$
142: if (simpleName != null)
143: output.append(simpleName);
144: else
145: output.append("*"); //$NON-NLS-1$
146: output.append(">"); //$NON-NLS-1$
147: return super.print(output);
148: }
149: }
|