Index: buildnotes_jdt-core.html
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/buildnotes_jdt-core.html,v
retrieving revision 1.3354
diff -u -r1.3354 buildnotes_jdt-core.html
--- buildnotes_jdt-core.html 8 Oct 2004 12:05:44 -0000 1.3354
+++ buildnotes_jdt-core.html 8 Oct 2004 12:15:54 -0000
@@ -53,7 +53,9 @@
Problem Reports Fixed
-73671
+73277
+[1.5][Search] Fields search does not work with generics
+73671
[1.5] Signature.getTypeArguments should also tolerate normal types
73078
ISourceManipulation.delete() tries to run in WorkspaceRoot scheduling rule
Index: model/org/eclipse/jdt/core/Signature.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java,v
retrieving revision 1.54
diff -u -r1.54 Signature.java
--- model/org/eclipse/jdt/core/Signature.java 8 Oct 2004 12:05:44 -0000 1.54
+++ model/org/eclipse/jdt/core/Signature.java 8 Oct 2004 12:15:54 -0000
@@ -1443,7 +1443,10 @@
* @since 3.1
*/
public static char[][] getTypeArguments(char[] parameterizedTypeSignature) throws IllegalArgumentException {
- int start = CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature);
+ int lastDot = CharOperation.lastIndexOf(C_DOT, parameterizedTypeSignature);
+ int start = lastDot == -1
+ ? CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature)
+ : CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature, lastDot+1);
if (start == -1)
return CharOperation.NO_CHAR_CHAR;
ArrayList args = new ArrayList();
@@ -1492,12 +1495,37 @@
* @since 3.1
*/
public static char[] getTypeErasure(char[] parameterizedTypeSignature) throws IllegalArgumentException {
- int genericStart = CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature);
- if (genericStart == -1) return parameterizedTypeSignature;
- char[] result = new char[genericStart+1];
- System.arraycopy(parameterizedTypeSignature, 0, result, 0, genericStart);
- result[genericStart] = C_SEMICOLON;
- return result;
+ int end = CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature);
+ if (end == -1) return parameterizedTypeSignature;
+ int length = parameterizedTypeSignature.length;
+ char[] result = new char[length];
+ int pos = 0;
+ int start = 0;
+ int deep= 0;
+ for (int idx=end; idx 0) throw new IllegalArgumentException();
+ int size = pos+length-start;
+ char[] resized = new char[size];
+ System.arraycopy(result, 0, resized, 0, pos);
+ System.arraycopy(parameterizedTypeSignature, start, resized, pos, length-start);
+ return resized;
}
/**
Index: model/org/eclipse/jdt/internal/core/BinaryType.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java,v
retrieving revision 1.90
diff -u -r1.90 BinaryType.java
--- model/org/eclipse/jdt/internal/core/BinaryType.java 6 Oct 2004 10:51:17 -0000 1.90
+++ model/org/eclipse/jdt/internal/core/BinaryType.java 8 Oct 2004 12:15:54 -0000
@@ -466,7 +466,8 @@
return typeParameters;
}
-// SEARCH_15 Get type parameter names
+// Get type parameter names
+// TODO (frederic) see if this method needs to be added to API
public char[][] getTypeParameterNames() throws JavaModelException {
String[] typeParameterSignatures = getTypeParameterSignatures();
int length = typeParameterSignatures.length;
Index: model/org/eclipse/jdt/internal/core/JavaProject.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java,v
retrieving revision 1.324
diff -u -r1.324 JavaProject.java
--- model/org/eclipse/jdt/internal/core/JavaProject.java 1 Oct 2004 14:26:42 -0000 1.324
+++ model/org/eclipse/jdt/internal/core/JavaProject.java 8 Oct 2004 12:15:54 -0000
@@ -127,7 +127,7 @@
/**
* Name of file containing custom project preferences
* @deprecated WARNING Visibility will be reduce to private before M9
- * If you use this variable, change your implementation to avoid future comilation error...
+ * If you use this variable, change your implementation to avoid future compilation error...
* @see bug 59258
* TODO (frederic) set visibility from public to private
*/
Index: model/org/eclipse/jdt/internal/core/SourceType.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java,v
retrieving revision 1.99
diff -u -r1.99 SourceType.java
--- model/org/eclipse/jdt/internal/core/SourceType.java 7 Oct 2004 13:27:30 -0000 1.99
+++ model/org/eclipse/jdt/internal/core/SourceType.java 8 Oct 2004 12:15:54 -0000
@@ -407,7 +407,8 @@
return info.typeParameters;
}
-// SEARCH_15 Get type parameter names
+// Get type parameter names
+// TODO (frederic) see if this method needs to be added to API
public char[][] getTypeParameterNames() throws JavaModelException {
SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
return info.getTypeParameterNames();
Index: search/org/eclipse/jdt/core/search/SearchPattern.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java,v
retrieving revision 1.20
diff -u -r1.20 SearchPattern.java
--- search/org/eclipse/jdt/core/search/SearchPattern.java 6 Oct 2004 14:31:57 -0000 1.20
+++ search/org/eclipse/jdt/core/search/SearchPattern.java 8 Oct 2004 12:15:54 -0000
@@ -752,9 +752,7 @@
*/
/* (non-Javadoc)
* SEARCH_15
- * Modified to handle generics.
- * Note that no change are done for declaration patterns as the search works well for generics
- * without any additional information.
+ * Modified to handle generics:
* 1) Field defined on parameterized types
* In this case, we need to split the erasure name and type argument names.
* Erasure name is used as type simple name and type argument names
@@ -762,6 +760,8 @@
* 2) Generic types declaration
* In this case, type arguments names are got from IType and stored
* in instanciated type reference pattern.
+ * Note that no change was done for declaration patterns as the search works well for generics
+ * without any additional information.
*/
public static SearchPattern createPattern(IJavaElement element, int limitTo) {
SearchPattern searchPattern = null;
@@ -779,28 +779,51 @@
char[] typeSimpleName;
char[] typeQualification;
char[][] typeNames = null;
+ int[] wildcards = null;
try {
char[] typeSignature = field.getTypeSignature().toCharArray();
- // SEARCH_15 (start)
char[] typeErasure = null;
if (CharOperation.indexOf(Signature.C_GENERIC_START, typeSignature) == -1) {
typeErasure = Signature.toCharArray(typeSignature);
} else {
typeErasure = Signature.toCharArray(Signature.getTypeErasure(typeSignature));
CharOperation.replace(typeErasure, '$', '.');
- if ((typeNames = Signature.getTypeArguments(typeSignature)) != null) {
+ try {
+ typeNames = Signature.getTypeArguments(typeSignature);
+ }
+ catch (IllegalArgumentException iae) {
+ // do nothing
+ }
+ if (typeNames != null) {
int length = typeNames.length;
+ wildcards = new int[length];
for (int i=0; i
- * 2) '*' is not treated yet inside <>
- * 3) that nested <> are not treated yet
- * 4) that only one type arguments definition is allowed
- * (ie. Gen.Member will be treated same as
- * Gen.Member pattern)
- * Using regexp syntax, we can described allowed patterns as:
+ *
+ * @since 3.1
+ * Type arguments can be specified to search references to parameterized types.
+ * Then patterns will look as follow:
* [qualification.] type [ '<' [ [ '?' {'extends'|'super'} ] type ( ',' [ '?' {'extends'|'super'} ] type )* ] '>' ]
+ * Please note that:
+ * - '*' is not valid inside type arguments definition <>
+ * - '?' is treated as a wildcard when it is inside <> (ie. it must be put on first position of the type argument)
+ * - nested <> are not allowed; List> will be treated as pattern List
+ * - only one type arguments definition is allowed; Gen.Member
+ * will be treated as pattern Gen.Member
*/
private static SearchPattern createTypePattern(String patternString, int limitTo, int matchRule) {
@@ -1185,14 +1203,14 @@
int parameterized = 0;
int paramPtr = -1;
char[][] paramNames = null;
- int[] wildcards = new int[10];
+ int[] wildcards = null;
while (token != TerminalTokens.TokenNameEOF) {
if (token != TerminalTokens.TokenNameWHITESPACE) {
if (storeParam) {
switch (token) {
case TerminalTokens.TokenNameMULTIPLY:
if (parameterized > 0) {
- // SEARCH_15 (frederic) Not treated yet...
+ // TODO (frederic) Should warn user that syntax is not valid
}
break;
case TerminalTokens.TokenNameQUESTION:
@@ -1200,7 +1218,7 @@
if (wildcards[paramPtr] == -1) {
wildcards[paramPtr] = Wildcard.UNBOUND;
} else {
- // SEARCH_15 (frederic) Invalid syntax
+ // TODO (frederic) Should warn user that syntax is not valid
}
}
break;
@@ -1209,7 +1227,7 @@
if (wildcards[paramPtr] == Wildcard.UNBOUND) {
wildcards[paramPtr] = Wildcard.EXTENDS;
} else {
- // SEARCH_15 (frederic) Invalid syntax
+ // TODO (frederic) Should warn user that syntax is not valid
}
}
break;
@@ -1218,7 +1236,7 @@
if (wildcards[paramPtr] == Wildcard.UNBOUND) {
wildcards[paramPtr] = Wildcard.SUPER;
} else {
- // SEARCH_15 (frederic) Invalid syntax
+ // TODO (frederic) Should warn user that syntax is not valid
}
}
break;
@@ -1236,6 +1254,7 @@
if (parameterized == 0) {
paramNames = new char[10][]; // 10 parameters max
paramPtr++;
+ wildcards = new int[10]; // 10 parameters max
wildcards[paramPtr] = -1;
storeType = false;
}
@@ -1340,8 +1359,7 @@
}
}
/**
- * Returns the enclosing type names of the given type.
- * TODO (frederic) Add-on for generic search
+ * Returns the type parameter names of the given type.
*/
private static char[][] typeParameterNames(IType type) {
char[][] paramNames = null;
Index: search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java,v
retrieving revision 1.24
diff -u -r1.24 FieldLocator.java
--- search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java 6 Oct 2004 12:42:55 -0000 1.24
+++ search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java 8 Oct 2004 12:15:54 -0000
@@ -30,6 +30,13 @@
this.isDeclarationOfAccessedFieldsPattern = this.pattern instanceof DeclarationOfAccessedFieldsPattern;
}
+/*
+ * Get binding of type argument from an index position.
+ * Delegate this search to the pattern which can cache results.
+ */
+protected TypeBinding getTypeNameBinding(int index) {
+ return ((FieldPattern) this.pattern).getTypeNameBinding(this.unitScope, index);
+}
//public int match(ASTNode node, MatchingNodeSet nodeSet) - SKIP IT
//public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
public int match(FieldDeclaration node, MatchingNodeSet nodeSet) {
@@ -84,47 +91,13 @@
// look at field type only if declaring type is not specified
if (fieldPattern.declaringSimpleName == null) return declaringLevel;
- int typeLevel = resolveLevelForType(fieldPattern.typeSimpleName, fieldPattern.typeQualification, field.type);
-
- // SEARCH_15 (frederic) Specific field pattern verification for generics (not fully tested yet...)
- if (typeLevel == IMPOSSIBLE_MATCH) {
- return IMPOSSIBLE_MATCH;
- }
- TypeBinding typeBinding = field.type;
- if (typeBinding != null) {
- boolean isParameterized = typeBinding.isParameterizedType();
- boolean isRawType = typeBinding.isRawType();
- if (fieldPattern.typeNames== null) {
- if (isParameterized && !isRawType) return IMPOSSIBLE_MATCH;
- } else {
- if (!isParameterized) return IMPOSSIBLE_MATCH;
- ParameterizedTypeBinding paramTypeBinding = (ParameterizedTypeBinding) typeBinding;
- if (paramTypeBinding.arguments == null) {
- return IMPOSSIBLE_MATCH;
- }
- int length = fieldPattern.typeNames.length;
- if (paramTypeBinding.arguments.length != length) return IMPOSSIBLE_MATCH;
- for (int i= 0; i typeLevel ? typeLevel : declaringLevel; // return the weaker match
}
protected int matchReference(Reference node, MatchingNodeSet nodeSet, boolean writeOnlyAccess) {
@@ -315,5 +288,39 @@
}
}
return IMPOSSIBLE_MATCH;
+}
+/* (non-Javadoc)
+ * Resolve level for type with a given binding.
+ */
+protected int resolveLevelForType(TypeBinding typeBinding) {
+ FieldPattern fieldPattern = (FieldPattern) this.pattern;
+ return resolveLevelForType(
+ fieldPattern.typeSimpleName,
+ fieldPattern.typeQualification,
+ fieldPattern.typeNames,
+ fieldPattern.wildcards,
+ ((InternalSearchPattern)this.pattern).mustResolve,
+ fieldPattern.declaration,
+ typeBinding);
+}
+/* (non-Javadoc)
+ * Overrides PatternLocator method behavior in order to accept member pattern as X.Member
+ * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#resolveLevelForType(char[], char[], org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+protected int resolveLevelForType (char[] simpleNamePattern, char[] qualificationPattern, TypeBinding type) {
+ char[] qualifiedPattern = getQualifiedPattern(simpleNamePattern, qualificationPattern);
+ int level = resolveLevelForType(qualifiedPattern, type);
+ if (level == ACCURATE_MATCH || type == null) return level;
+ boolean match = false;
+ if (type.isMemberType() || type.isLocalType()) {
+ if (qualificationPattern != null) {
+ match = CharOperation.equals(qualifiedPattern, getQualifiedSourceName(type), this.isCaseSensitive);
+ } else {
+ match = CharOperation.equals(qualifiedPattern, type.sourceName(), this.isCaseSensitive);
+ }
+ } else if (qualificationPattern == null) {
+ match = CharOperation.equals(qualifiedPattern, getQualifiedSourceName(type), this.isCaseSensitive);
+ }
+ return match ? ACCURATE_MATCH : IMPOSSIBLE_MATCH;
}
}
Index: search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java,v
retrieving revision 1.19
diff -u -r1.19 FieldPattern.java
--- search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java 6 Oct 2004 12:42:55 -0000 1.19
+++ search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java 8 Oct 2004 12:15:54 -0000
@@ -12,6 +12,8 @@
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
public class FieldPattern extends VariablePattern implements IIndexConstants {
@@ -24,8 +26,11 @@
protected char[] typeQualification;
protected char[] typeSimpleName;
-// SEARCH_15 Store type names
-protected char[][] typeNames;
+// Additional information for generics search
+protected boolean declaration; // show whether the search is based on a declaration or an instance
+protected char[][] typeNames; // type arguments names storage
+protected TypeBinding[] typeBindings; // cache for type arguments bindings
+protected int[] wildcards; // show wildcard kind for each type arguments
protected static char[][] REF_CATEGORIES = { REF };
protected static char[][] REF_AND_DECL_CATEGORIES = { REF, FIELD_DECL };
@@ -55,7 +60,9 @@
((InternalSearchPattern)this).mustResolve = mustResolve();
}
-// SEARCH_15 Create field pattern with generics additional information
+/*
+ * Instanciate a field pattern with additional information for generics search
+ */
public FieldPattern(
boolean findDeclarations,
boolean readAccess,
@@ -66,6 +73,7 @@
char[] typeQualification,
char[] typeSimpleName,
char[][] typeNames,
+ int[] wildcards,
int matchRule) {
this(findDeclarations, readAccess, writeAccess, name, declaringQualification, declaringSimpleName, typeQualification, typeSimpleName, matchRule);
@@ -73,6 +81,7 @@
if (typeNames != null) {
this.typeNames= typeNames;
}
+ this.wildcards = wildcards;
}
public void decodeIndexKey(char[] key) {
this.name = key;
@@ -89,6 +98,25 @@
if (this.findDeclarations)
return DECL_CATEGORIES;
return CharOperation.NO_CHAR_CHAR;
+}
+/*
+ * Get binding of type argument from a class unit scope and its index position.
+ * Cache is lazy initialized and if no binding is found, then store a problem binding
+ * to avoid making research twice...
+ */
+protected TypeBinding getTypeNameBinding(CompilationUnitScope unitScope, int index) {
+ int length = this.typeNames.length;
+ if (this.typeBindings == null) this.typeBindings = new TypeBinding[length];
+ if (index <0 || index > length) return null;
+ TypeBinding typeBinding = this.typeBindings[index];
+ if (typeBinding == null) {
+ typeBinding = unitScope.getType(this.typeNames[index]);
+ this.typeBindings[index] = typeBinding;
+ }
+ if (!typeBinding.isValidBinding()) {
+ typeBinding = null;
+ }
+ return typeBinding;
}
public boolean matchesDecodedKey(SearchPattern decodedPattern) {
return true; // index key is not encoded so query results all match
Index: search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java,v
retrieving revision 1.202
diff -u -r1.202 MatchLocator.java
--- search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java 8 Oct 2004 10:09:21 -0000 1.202
+++ search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java 8 Oct 2004 12:15:54 -0000
@@ -58,8 +58,6 @@
public SearchRequestor requestor;
public IJavaSearchScope scope;
public IProgressMonitor progressMonitor;
-// SEARCH_15
-public CompilationUnitScope unitScope;
public org.eclipse.jdt.core.ICompilationUnit[] workingCopies;
public HandleFactory handleFactory;
@@ -1286,7 +1284,7 @@
}
/**
- * SEARCH_15
+ * @since 3.1
* Finds the accurate positions of the sequence of tokens given by qualifiedName
* in the source and reports a reference to this this qualified name
* to the search requestor.
@@ -1316,11 +1314,18 @@
if (token == TerminalTokens.TokenNameIdentifier && this.pattern.matchesName(name, scanner.getCurrentTokenSource())) {
// extends selection end for parameterized types if necessary
try {
- while (token != TerminalTokens.TokenNameGREATER) {
+ int count = 0;
+ while (token != TerminalTokens.TokenNameGREATER || count > 0) {
token = scanner.getNextToken();
- if (token == TerminalTokens.TokenNameEOF) {
- // TODO (search-frederic) Abnormal end of file, perhaps trace something in DEBUG
- return;
+ switch (token) {
+ case TerminalTokens.TokenNameLESS:
+ count++;
+ break;
+ case TerminalTokens.TokenNameGREATER:
+ count--;
+ break;
+ case TerminalTokens.TokenNameEOF:
+ return;
}
}
} catch (InvalidInputException e1) {
@@ -1487,15 +1492,12 @@
}
/**
* Visit the given resolved parse tree and report the nodes that match the search pattern.
- * SEARCH_15
- * Add unit scope storage in pattern locator. This will allow some additional verification
- * while resolving levels of type arguments.
*/
protected void reportMatching(CompilationUnitDeclaration unit, boolean mustResolve) throws CoreException {
MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet;
if (mustResolve) {
- this.unitScope = unit.scope.compilationUnitScope();
- this.patternLocator.unitScope = this.unitScope;
+ CompilationUnitScope unitScope= unit.scope.compilationUnitScope();
+ this.patternLocator.unitScope = unitScope;
// move the possible matching nodes that exactly match the search pattern to the matching nodes set
Object[] nodes = nodeSet.possibleMatchingNodesSet.values;
for (int i = 0, l = nodes.length; i < l; i++) {
@@ -1516,7 +1518,6 @@
}
nodeSet.possibleMatchingNodesSet = new SimpleSet(3);
} else {
- this.unitScope = null;
this.patternLocator.unitScope = null;
}
Index: search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java,v
retrieving revision 1.26
diff -u -r1.26 PatternLocator.java
--- search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java 6 Oct 2004 10:51:17 -0000 1.26
+++ search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java 8 Oct 2004 12:15:54 -0000
@@ -22,7 +22,6 @@
protected int matchMode;
protected boolean isCaseSensitive;
-// SEARCH_15
protected CompilationUnitScope unitScope;
/* match levels */
@@ -92,6 +91,45 @@
this.isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
this.matchMode = matchRule - (this.isCaseSensitive ? SearchPattern.R_CASE_SENSITIVE : 0);
}
+/* (non-Javadoc)
+ * Modify PatternLocator.qualifiedPattern behavior:
+ * do not add star before simple name pattern when qualification pattern is null.
+ * This avoid to match p.X when pattern is only X...
+ */
+protected char[] getQualifiedPattern(char[] simpleNamePattern, char[] qualificationPattern) {
+ // NOTE: if case insensitive search then simpleNamePattern & qualificationPattern are assumed to be lowercase
+ if (simpleNamePattern == null) {
+ if (qualificationPattern == null) return null;
+ return CharOperation.concat(qualificationPattern, ONE_STAR, '.');
+ } else if (qualificationPattern == null) {
+ return simpleNamePattern;
+ } else {
+ return CharOperation.concat(qualificationPattern, simpleNamePattern, '.');
+ }
+}
+/* (non-Javadoc)
+ * Modify PatternLocator.qualifiedSourceName behavior:
+ * also concatene enclosing type name when type is a only a member type.
+ */
+protected char[] getQualifiedSourceName(TypeBinding binding) {
+ if (binding instanceof ReferenceBinding) {
+ ReferenceBinding type = (ReferenceBinding) binding;
+ if (type.isLocalType()) {
+ return CharOperation.concat(qualifiedSourceName(type.enclosingType()), new char[] {'.', '1', '.'}, type.sourceName());
+ } else if (type.isMemberType()) {
+ return CharOperation.concat(qualifiedSourceName(type.enclosingType()), type.sourceName(), '.');
+ }
+ }
+ return binding != null ? binding.qualifiedSourceName() : null;
+}
+/*
+ * Get binding of type argument from a class unit scope and its index position.
+ * Cache is lazy initialized and if no binding is found, then store a problem binding
+ * to avoid making research twice...
+ */
+protected TypeBinding getTypeNameBinding(int index) {
+ return null;
+}
/**
* Initializes this search pattern so that polymorphic search can be performed.
*/
@@ -316,6 +354,173 @@
return CharOperation.match(qualifiedPattern, fullyQualifiedTypeName, this.isCaseSensitive)
? ACCURATE_MATCH
: IMPOSSIBLE_MATCH;
+}
+/* (non-Javadoc)
+ * Resolve level for type with a given binding with all pattern information.
+ */
+protected int resolveLevelForType (char[] simpleNamePattern,
+ char[] qualificationPattern,
+ char[][] typeNames,
+ int[] wildcards,
+ boolean mustResolve,
+ boolean declaration,
+ TypeBinding type) {
+ // standard search with no generic additional information must succeed
+ int level = resolveLevelForType(simpleNamePattern, qualificationPattern, type);
+ if (level == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
+ if (type == null) return level;
+
+ // pattern has no type parameter, return standard result
+ if (typeNames == null || typeNames.length == 0) {
+ return level;
+ }
+
+ // pattern has type parameter(s) or type argument(s)
+ boolean isRawType = type.isRawType();
+ if (type.isGenericType()) {
+ // Binding is generic, get its type variable(s)
+ TypeVariableBinding[] typeVariables = null;
+ if (type instanceof SourceTypeBinding) {
+ SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) type;
+ typeVariables = sourceTypeBinding.typeVariables;
+ } else if (type instanceof BinaryTypeBinding) {
+ BinaryTypeBinding binaryTypeBinding = (BinaryTypeBinding) type;
+ if (mustResolve)
+ typeVariables = binaryTypeBinding.typeVariables(); // TODO (frederic) verify performance
+ }
+ // type variables length must match at least specified type names length
+ if (typeVariables == null || typeVariables.length == 0) {
+ return IMPOSSIBLE_MATCH;
+ }
+ int length = typeNames.length;
+ if (typeVariables.length != length) return IMPOSSIBLE_MATCH;
+ // TODO (frederic) do we need to verify each parameter?
+ return level; // we can't do better
+ } else if (!type.isParameterizedType() && !isRawType) {
+ // Standard types (ie. neither generic nor parameterized nor raw types)
+ // cannot match pattern with type parameters or arguments
+ return IMPOSSIBLE_MATCH;
+ } else {
+ // Binding is parameterized type
+ ParameterizedTypeBinding paramTypeBinding = (ParameterizedTypeBinding) type;
+ if (paramTypeBinding.arguments == null) {
+ // binding has no type parameters => ok for raw types
+ if (isRawType) return level;
+ // need to verify hierarchy for member types (raw type of generic member
+ // are stored as parameterized types...)
+ if (type.isMemberType() && qualificationPattern != null) {
+ int lastDot = CharOperation.lastIndexOf('.', qualificationPattern);
+ char[] enclosingQualificationPattern = lastDot==-1 ? null : CharOperation.subarray(qualificationPattern, 0, lastDot);
+ char[] enclosingSimpleNamePattern = lastDot==-1 ? qualificationPattern : CharOperation.subarray(qualificationPattern, lastDot+1, qualificationPattern.length);
+ if (resolveLevelForType(enclosingSimpleNamePattern, enclosingQualificationPattern, typeNames, wildcards, mustResolve, declaration, paramTypeBinding.enclosingType()) == IMPOSSIBLE_MATCH) {
+ return IMPOSSIBLE_MATCH;
+ }
+ return level;
+ }
+ return IMPOSSIBLE_MATCH;
+ }
+
+ // type parameters length must match at least specified type names length
+ int length = typeNames.length;
+ if (paramTypeBinding.arguments.length != length) return IMPOSSIBLE_MATCH;
+
+ // for generic type declaration, verification is different than for parameterized type
+ if (declaration) {
+ // TODO (frederic) more verification to do here with type parameter bounds?
+ return level;
+ }
+
+ // verify each pattern type parameter
+ nextTypeArgument: for (int i= 0; i verify that types are compatible
+ if (argTypeBinding == patternBinding) continue;
+ if (argTypeBinding.isWildcard()) {
+ TypeBinding bound = ((WildcardBinding) argTypeBinding).bound;
+ switch (patternWildcard) {
+ case Wildcard.SUPER:
+ if (bound == null || patternBinding.isCompatibleWith(bound))
+ // argument type is in bound hierarchy => match
+ continue;
+ break;
+ case Wildcard.EXTENDS:
+ if (bound == null || bound.isCompatibleWith(patternBinding))
+ // argument type is a subclass of bound => match
+ continue;
+ break;
+ default: //UNBOUND
+ // there's no bound name => match
+ continue;
+ }
+ }
+ return IMPOSSIBLE_MATCH;
+ }
+
+ // pattern hasn't be solved, try to see if names match in hierarchy
+ // First if type argument is a wildcard
+ if (argTypeBinding.isWildcard()) {
+ WildcardBinding wildcardBinding = (WildcardBinding) argTypeBinding;
+ switch (wildcardBinding.kind) {
+ case Wildcard.EXTENDS:
+ // We cannot know in this case...
+ level = INACCURATE_MATCH;
+ case Wildcard.UNBOUND:
+ // there's no bound name to match => valid
+ continue;
+ }
+ // try to match name in hierarchy
+ ReferenceBinding boundBinding = (ReferenceBinding) wildcardBinding.bound;
+ while (boundBinding != null) {
+ if (CharOperation.equals(argType, boundBinding.shortReadableName(), this.isCaseSensitive) ||
+ CharOperation.equals(argType, boundBinding.readableName(), this.isCaseSensitive)) {
+ // found name in hierarchy => match
+ continue nextTypeArgument;
+ }
+ boundBinding = boundBinding.superclass();
+ }
+ return IMPOSSIBLE_MATCH;
+ }
+
+ // try to match names when there's no wildcard
+ // first get real binding
+ ReferenceBinding refBinding = null;
+ if (argTypeBinding.isArrayType()) {
+ TypeBinding leafBinding = ((ArrayBinding) argTypeBinding).leafComponentType;
+ if (!leafBinding.isBaseType()) {
+ refBinding = (ReferenceBinding) leafBinding;
+ }
+ } else if (!argTypeBinding.isBaseType()) {
+ refBinding = (ReferenceBinding) argTypeBinding;
+ }
+ // Compare name
+ if (refBinding == null) {
+ // Based type
+ if (!CharOperation.equals(argType, argTypeBinding.shortReadableName(), this.isCaseSensitive) &&
+ !CharOperation.equals(argType, argTypeBinding.readableName(), this.isCaseSensitive)) {
+ return IMPOSSIBLE_MATCH;
+ }
+ } else {
+ while (refBinding != null) {
+ if (CharOperation.equals(argType, refBinding.shortReadableName(), this.isCaseSensitive) ||
+ CharOperation.equals(argType, refBinding.readableName(), this.isCaseSensitive)) {
+ // found name in hierarchy => match
+ continue nextTypeArgument;
+ }
+ refBinding = refBinding.superclass();
+ }
+ return IMPOSSIBLE_MATCH;
+ }
+ }
+ return level;
+ }
}
public String toString(){
return "SearchPattern"; //$NON-NLS-1$
Index: search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java,v
retrieving revision 1.23
diff -u -r1.23 TypeReferenceLocator.java
--- search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java 6 Oct 2004 10:51:22 -0000 1.23
+++ search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java 8 Oct 2004 12:15:54 -0000
@@ -31,37 +31,6 @@
this.pattern = pattern;
this.isDeclarationOfReferencedTypesPattern = this.pattern instanceof DeclarationOfReferencedTypesPattern;
}
-/* SEARCH_15
- * Modify PatternLocator.qualifiedPattern behavior:
- * do not add star before simple name pattern when qualification pattern is null.
- * This avoid to match p.X when pattern is X...
- */
-public static char[] qualifiedPattern(char[] simpleNamePattern, char[] qualificationPattern) {
- // NOTE: if case insensitive search then simpleNamePattern & qualificationPattern are assumed to be lowercase
- if (simpleNamePattern == null) {
- if (qualificationPattern == null) return null;
- return CharOperation.concat(qualificationPattern, ONE_STAR, '.');
- } else if (qualificationPattern == null) {
- return simpleNamePattern;
- } else {
- return CharOperation.concat(qualificationPattern, simpleNamePattern, '.');
- }
-}
-/* SEARCH_15
- * Modify PatternLocator.qualifiedSourceName behavior:
- * concat enclosing type when type is a only a member type.
- */
-public static char[] qualifiedSourceName(TypeBinding binding) {
- if (binding instanceof ReferenceBinding) {
- ReferenceBinding type = (ReferenceBinding) binding;
- if (type.isLocalType()) {
- return CharOperation.concat(qualifiedSourceName(type.enclosingType()), new char[] {'.', '1', '.'}, type.sourceName());
- } else if (type.isMemberType()) {
- return CharOperation.concat(qualifiedSourceName(type.enclosingType()), type.sourceName(), '.');
- }
- }
- return binding != null ? binding.qualifiedSourceName() : null;
-}
protected IJavaElement findElement(IJavaElement element, int accuracy) {
// need exact match to be able to open on type ref
if (accuracy != SearchMatch.A_ACCURATE) return null;
@@ -72,6 +41,13 @@
element = element.getParent();
return element;
}
+/*
+ * Get binding of type argument from an index position.
+ * Delegate this search to the pattern which can cache results.
+ */
+protected TypeBinding getTypeNameBinding(int index) {
+ return this.pattern.getTypeNameBinding(this.unitScope, index);
+}
public int match(ASTNode node, MatchingNodeSet nodeSet) { // interested in ImportReference
if (!(node instanceof ImportReference)) return IMPOSSIBLE_MATCH;
@@ -144,7 +120,7 @@
}
protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
if (this.pattern.shouldExtendSelection()) {
- // SEARCH_15 do not report import ref for generic patterns...
+ // do not report import ref for generic patterns...
return;
}
if (this.isDeclarationOfReferencedTypesPattern) {
@@ -193,7 +169,7 @@
locator.report(match);
}
} else if (this.pattern.shouldExtendSelection() && arrayRef.resolvedType.isParameterizedType() && ((ParameterizedTypeBinding)arrayRef.resolvedType).arguments != null) {
- // SEARCH_15 specific report accurate match for parameterized types
+ // specific report accurate match for parameterized types
locator.reportAccurateParameterizedTypeReference(arrayRef, this.pattern.simpleName, element, accuracy);
} else
locator.reportAccurateTypeReference(arrayRef, this.pattern.simpleName, element, accuracy);
@@ -287,7 +263,7 @@
int start = (int) ((positions[this.pattern.qualification == null ? lastIndex : 0]) >>> 32);
int end = (int) positions[lastIndex];
if (this.pattern.shouldExtendSelection() && refBinding.isParameterizedType() && ((ParameterizedTypeBinding)refBinding).arguments != null) {
- // SEARCH_15 specific report accurate match for parameterized types
+ // specific report accurate match for parameterized types
locator.reportAccurateParameterizedTypeReference(qTypeRef, this.pattern.simpleName, element, accuracy);
} else {
SearchMatch match = locator.newTypeReferenceMatch(element, accuracy, start, end-start+1, qTypeRef);
@@ -480,7 +456,6 @@
return resolveLevelForTypeOrEnclosingTypes(this.pattern.simpleName, this.pattern.qualification, typeBinding);
}
/* (non-Javadoc)
- * SEARCH_15
* Resolve level for type with a given binding.
* This is just an helper to avoid call of method with all parameters...
*/
@@ -489,189 +464,30 @@
this.pattern.simpleName,
this.pattern.qualification,
this.pattern.typeNames,
+ this.pattern.wildcards,
((InternalSearchPattern)this.pattern).mustResolve,
this.pattern.declaration,
typeBinding);
}
/* (non-Javadoc)
- * SEARCH_15
* Overrides PatternLocator method behavior in order to accept member pattern as X.Member
* @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#resolveLevelForType(char[], char[], org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
*/
protected int resolveLevelForType (char[] simpleNamePattern, char[] qualificationPattern, TypeBinding type) {
- char[] qualifiedPattern = qualifiedPattern(simpleNamePattern, qualificationPattern);
+ char[] qualifiedPattern = getQualifiedPattern(simpleNamePattern, qualificationPattern);
int level = resolveLevelForType(qualifiedPattern, type);
if (level == ACCURATE_MATCH || type == null) return level;
boolean match = false;
if (type.isMemberType() || type.isLocalType()) {
if (qualificationPattern != null) {
- match = CharOperation.equals(qualifiedPattern, qualifiedSourceName(type), this.isCaseSensitive);
+ match = CharOperation.equals(qualifiedPattern, getQualifiedSourceName(type), this.isCaseSensitive);
} else {
match = CharOperation.equals(qualifiedPattern, type.sourceName(), this.isCaseSensitive);
}
} else if (qualificationPattern == null) {
- match = CharOperation.equals(qualifiedPattern, qualifiedSourceName(type), this.isCaseSensitive);
+ match = CharOperation.equals(qualifiedPattern, getQualifiedSourceName(type), this.isCaseSensitive);
}
return match ? ACCURATE_MATCH : IMPOSSIBLE_MATCH;
-}
-/* (non-Javadoc)
- * SEARCH_15
- * Resolve level for type with a given binding with all pattern information.
- */
-protected int resolveLevelForType (char[] simpleNamePattern,
- char[] qualificationPattern,
- char[][] typeNames,
- boolean mustResolve,
- boolean declaration,
- TypeBinding type) {
- int level = resolveLevelForType(simpleNamePattern, qualificationPattern, type);
- if (level == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
- if (type == null) return level;
-
- // pattern has no type parameter
- if (typeNames == null || typeNames.length == 0) {
- return level;
- }
-
- // pattern has type parameter(s) or type argument(s)
- boolean isRawType = type.isRawType();
- if (type.isGenericType()) {
- // Binding is generic, get its type variable(s)
- TypeVariableBinding[] typeVariables = null;
- if (type instanceof SourceTypeBinding) {
- SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) type;
- typeVariables = sourceTypeBinding.typeVariables;
- } else if (type instanceof BinaryTypeBinding) {
- BinaryTypeBinding binaryTypeBinding = (BinaryTypeBinding) type;
- if (mustResolve)
- typeVariables = binaryTypeBinding.typeVariables(); // TODO (frederic) do we really want to resolve?
- }
- // type variables length must match at least specified type names length
- if (typeVariables == null || typeVariables.length == 0) {
- return IMPOSSIBLE_MATCH;
- }
- int length = typeNames.length;
- if (typeVariables.length != length) return IMPOSSIBLE_MATCH;
- // verify each parameters
- return level; // we can't do better
- // TODO (frederic) need to do more verifications here?
- } else if (!type.isParameterizedType() && !isRawType) {
- // Standard types (ie. neither generic nor parameterized nor raw types)
- // cannot match pattern when it has type parameters or arguments
- return IMPOSSIBLE_MATCH;
- } else {
- // Binding is parameterized type
- ParameterizedTypeBinding paramTypeBinding = (ParameterizedTypeBinding) type;
- if (paramTypeBinding.arguments == null) {
- // binding has no type parameters => ok for raw types
- if (isRawType) return level;
- // need to verify hierarchy for member types
- if (type.isMemberType() && qualificationPattern != null) {
- int lastDot = CharOperation.lastIndexOf('.', qualificationPattern);
- char[] enclosingQualificationPattern = lastDot==-1 ? null : CharOperation.subarray(qualificationPattern, 0, lastDot);
- char[] enclosingSimpleNamePattern = lastDot==-1 ? qualificationPattern : CharOperation.subarray(qualificationPattern, lastDot+1, qualificationPattern.length);
- if (resolveLevelForType(enclosingSimpleNamePattern, enclosingQualificationPattern, typeNames, mustResolve, declaration, paramTypeBinding.enclosingType()) == IMPOSSIBLE_MATCH) {
- return IMPOSSIBLE_MATCH;
- }
- return level;
- }
- return IMPOSSIBLE_MATCH;
- }
- // type parameters length must match at least specified type names length
- int length = typeNames.length;
- if (paramTypeBinding.arguments.length != length) return IMPOSSIBLE_MATCH;
- // verify each type parameter
- if (declaration) {
- // TODO (frederic) more verification to do here with type parameter bounds?
- return level;
- }
- nextTypeArgument: for (int i= 0; i verify that types are compatible
- if (argTypeBinding == patternBinding) continue;
- if (argTypeBinding.isWildcard()) {
- TypeBinding bound = ((WildcardBinding) argTypeBinding).bound;
- if (this.pattern.wildcards != null) {
- switch (this.pattern.wildcards[i]) {
- case Wildcard.SUPER:
- if (bound == null || patternBinding.isCompatibleWith(bound))
- // argument type is in bound hierarchy => valid
- continue;
- break;
- case Wildcard.EXTENDS:
- if (bound == null || bound.isCompatibleWith(patternBinding))
- // argument type is a subclass of bound => valid
- continue;
- break;
- default: //UNBOUND
- // there's no bound name to match => valid
- continue;
- }
- }
- }
- return IMPOSSIBLE_MATCH;
- }
-
- // pattern hasn't be solved, try to see if names match in hierarchy
- // First if type argument is a wildcard
- if (argTypeBinding.isWildcard()) {
- WildcardBinding wildcardBinding = (WildcardBinding) argTypeBinding;
- switch (wildcardBinding.kind) {
- case Wildcard.EXTENDS:
- // We cannot know in this case...
- level = INACCURATE_MATCH;
- case Wildcard.UNBOUND:
- // there's no bound name to match => valid
- continue;
- }
- // try to match name in hierarchy
- ReferenceBinding boundBinding = (ReferenceBinding) wildcardBinding.bound;
- while (boundBinding != null) {
- if (CharOperation.equals(argType, boundBinding.shortReadableName(), this.isCaseSensitive) ||
- CharOperation.equals(argType, boundBinding.readableName(), this.isCaseSensitive)) {
- continue nextTypeArgument;
- }
- boundBinding = boundBinding.superclass();
- }
- return IMPOSSIBLE_MATCH;
- }
-
- // try to match names when there's no wildcard
- ReferenceBinding refBinding = null;
- if (argTypeBinding.isArrayType()) {
- TypeBinding leafBinding = ((ArrayBinding) argTypeBinding).leafComponentType;
- if (!leafBinding.isBaseType()) {
- refBinding = (ReferenceBinding) leafBinding;
- }
- } else if (!argTypeBinding.isBaseType()) {
- refBinding = (ReferenceBinding) argTypeBinding;
- }
- if (refBinding == null) {
- // Based type
- if (!CharOperation.equals(argType, argTypeBinding.shortReadableName(), this.isCaseSensitive) &&
- !CharOperation.equals(argType, argTypeBinding.readableName(), this.isCaseSensitive)) {
- return IMPOSSIBLE_MATCH;
- }
- } else {
- while (refBinding != null) {
- if (CharOperation.equals(argType, refBinding.shortReadableName(), this.isCaseSensitive) ||
- CharOperation.equals(argType, refBinding.readableName(), this.isCaseSensitive)) {
- continue nextTypeArgument;
- }
- refBinding = refBinding.superclass();
- }
- return IMPOSSIBLE_MATCH;
- }
- }
- return level;
- }
}
/**
* Returns whether the given type binding or one of its enclosing types
Index: search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java
===================================================================
RCS file: /data/cvs/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java,v
retrieving revision 1.64
diff -u -r1.64 TypeReferencePattern.java
--- search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java 6 Oct 2004 10:51:17 -0000 1.64
+++ search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java 8 Oct 2004 12:15:54 -0000
@@ -13,8 +13,6 @@
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
-import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
-import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
@@ -23,7 +21,7 @@
protected char[] qualification;
protected char[] simpleName;
-// SEARCH_15 Additional information for generics search
+// Additional information for generics search
protected boolean declaration; // show whether the search is based on a declaration or an instance
protected char[][] typeNames; // type arguments names storage
protected TypeBinding[] typeBindings; // cache for type arguments bindings
@@ -50,7 +48,9 @@
((InternalSearchPattern)this).mustResolve = true; // always resolve (in case of a simple name reference being a potential match)
}
-// SEARCH_15 Instanciate a type reference pattern with additional information for generics search
+/*
+ * Instanciate a type reference pattern with additional information for generics search
+ */
public TypeReferencePattern(char[] qualification, char[] simpleName, char[][] typeNames, boolean fromJavaElement, int[] wildcards, int matchRule) {
this(qualification, simpleName,matchRule);
@@ -94,12 +94,9 @@
TypeBinding typeBinding = this.typeBindings[index];
if (typeBinding == null) {
typeBinding = unitScope.getType(this.typeNames[index]);
- if (typeBinding == null) {
- this.typeBindings[index] = new ProblemReferenceBinding(this.typeNames[index], ProblemReasons.NotFound);
- } else {
- this.typeBindings[index] = typeBinding;
- }
- } else if (!typeBinding.isValidBinding()) {
+ this.typeBindings[index] = typeBinding;
+ }
+ if (!typeBinding.isValidBinding()) {
typeBinding = null;
}
return typeBinding;