Index: search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java,v retrieving revision 1.246 diff -u -r1.246 MatchLocator.java --- search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java 18 May 2005 14:45:17 -0000 1.246 +++ search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java 8 Jun 2005 14:36:15 -0000 @@ -39,6 +39,7 @@ import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.env.*; @@ -401,36 +402,6 @@ } return this.basicParser; } -/** - * Add the possibleMatch to the loop - * -> build compilation unit declarations, their bindings and record their results. - */ -protected void parseAndBuildBindings(PossibleMatch possibleMatch, boolean mustResolve) { - if (this.progressMonitor != null && this.progressMonitor.isCanceled()) - throw new OperationCanceledException(); - - try { - if (BasicSearchEngine.VERBOSE) - System.out.println("Parsing " + possibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$ - - this.parser.nodeSet = possibleMatch.nodeSet; - CompilationResult unitResult = new CompilationResult(possibleMatch, 1, 1, this.options.maxProblemsPerUnit); - CompilationUnitDeclaration parsedUnit = this.parser.dietParse(possibleMatch, unitResult); - if (parsedUnit != null) { - if (mustResolve && !parsedUnit.isEmpty()) - this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); - - // add the possibleMatch with its parsedUnit to matchesToProcess - possibleMatch.parsedUnit = parsedUnit; - int size = this.matchesToProcess.length; - if (this.numberOfMatches == size) - System.arraycopy(this.matchesToProcess, 0, this.matchesToProcess = new PossibleMatch[size == 0 ? 1 : size * 2], 0, this.numberOfMatches); - this.matchesToProcess[this.numberOfMatches++] = possibleMatch; - } - } finally { - this.parser.nodeSet = null; - } -} /* * Caches the given binary type in the lookup environment and returns it. * Returns the existing one if already cached. @@ -732,7 +703,7 @@ protected IType getFocusType() { return this.scope instanceof HierarchyScope ? ((HierarchyScope) this.scope).focusType : null; } -protected void getMethodBodies(CompilationUnitDeclaration unit) { +protected void getMethodBodies(CompilationUnitDeclaration unit, MatchingNodeSet nodeSet) { if (unit.ignoreMethodBodies) { unit.ignoreFurtherInvestigation = true; return; // if initial diet parse did not work, no need to dig into method bodies. @@ -751,7 +722,7 @@ char[] contents = compilationResult.compilationUnit.getContents(); this.parser.javadocParser.scanner.setSource(contents); } - this.parser.nodeSet = this.currentPossibleMatch.nodeSet; + this.parser.nodeSet = nodeSet; this.parser.parseBodies(unit); } finally { this.parser.nodeSet = null; @@ -776,31 +747,32 @@ this.bindings.put(typeKey, typeBinding); return typeBinding.isValidBinding() ? typeBinding : null; } -public MethodBinding getMethodBinding(IMethod method) { +public MethodBinding getMethodBinding(MethodPattern methodPattern) { if (this.unitScope == null) return null; // Try to get binding from cache - Binding binding = (Binding) this.bindings.get(method); + Binding binding = (Binding) this.bindings.get(methodPattern); if (binding != null) { if (binding instanceof MethodBinding && binding.isValidBinding()) return (MethodBinding) binding; return null; } // Get binding from unit scope - String typeName = method.getDeclaringType().getElementName(); - TypeBinding declaringTypeBinding = getType(typeName, typeName.toCharArray()); + char[] typeName = PatternLocator.qualifiedPattern(methodPattern.declaringSimpleName, methodPattern.declaringQualification); + if (typeName == null) { + if (methodPattern.declaringType == null) return null; + typeName = methodPattern.declaringType.getFullyQualifiedName().toCharArray(); + } + TypeBinding declaringTypeBinding = getType(typeName, typeName); if (declaringTypeBinding != null) { if (declaringTypeBinding.isArrayType()) { declaringTypeBinding = declaringTypeBinding.leafComponentType(); } if (!declaringTypeBinding.isBaseType()) { - String[] parameterTypes = method.getParameterTypes(); + char[][] parameterTypes = methodPattern.parameterSimpleNames; + if (parameterTypes == null) return null; int paramTypeslength = parameterTypes.length; - char[][] paramTypesChars = new char[paramTypeslength][]; - for (int i=0; i= ClassFileConstants.JDK1_5; boolean bindingsWereCreated = mustResolve; try { for (int i = start, maxUnits = start + length; i < maxUnits; i++) { PossibleMatch possibleMatch = possibleMatches[i]; try { - parseAndBuildBindings(possibleMatch, mustResolve); - if (!mustResolve) { + if (!parseAndBuildBindings(possibleMatch, mustResolvePattern)) continue; + // Currently we only need to resolve over pattern flag if there's potential parameterized types + if (this.patternLocator.mayBeGeneric) { + // If pattern does not resolve then rely on possible match node set resolution + // which may have been modified while locator was adding possible matches to it + if (!mustResolvePattern && !mustResolve) { + mustResolve = possibleMatch.nodeSet.mustResolve; + bindingsWereCreated = mustResolve; + } + } else { + // Reset matching node resolution with pattern one if there's no potential parameterized type + // to minimize side effect on previous search behavior + possibleMatch.nodeSet.mustResolve = mustResolvePattern; + } + // possible match node resolution has been merged with pattern one, so rely on it to know + // whether we need to process compilation unit now or later + if (!possibleMatch.nodeSet.mustResolve) { if (this.progressMonitor != null) { this.progressWorked++; if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep); } process(possibleMatch, bindingsWereCreated); + if (this.numberOfMatches>0 && this.matchesToProcess[this.numberOfMatches-1] == possibleMatch) { + // forget last possible match as it was processed + this.numberOfMatches--; + } } } finally { - if (!mustResolve) + if (!possibleMatch.nodeSet.mustResolve) possibleMatch.cleanUp(); } } @@ -1094,7 +1088,7 @@ } previousJavaProject = javaProject; } - matchSet.add(new PossibleMatch(this, resource, openable, searchDocument)); + matchSet.add(new PossibleMatch(this, resource, openable, searchDocument, ((InternalSearchPattern) this.pattern).mustResolve)); } // last project @@ -1133,7 +1127,7 @@ IJavaElement focus = ((InternalSearchPattern) searchPattern).focus; if (focus != null) { SearchDocument document = participant.getDocument(focus.getPath().toString()); - this.currentPossibleMatch = new PossibleMatch(this, focus.getResource(), null, document); + this.currentPossibleMatch = new PossibleMatch(this, focus.getResource(), null, document, ((InternalSearchPattern) searchPattern).mustResolve); if (encloses(focus)) { SearchMatch match = newDeclarationMatch(focus.getAncestor(IJavaElement.PACKAGE_FRAGMENT), null/*no binding*/, SearchMatch.A_ACCURATE, -1, -1); report(match); @@ -1174,7 +1168,7 @@ if (resource == null) // case of a file in an external jar resource = javaProject.getProject(); SearchDocument document = participant.getDocument(resource.getFullPath().toString()); - this.currentPossibleMatch = new PossibleMatch(this, resource, null, document); + this.currentPossibleMatch = new PossibleMatch(this, resource, null, document, ((InternalSearchPattern) searchPattern).mustResolve); try { if (encloses(pkg)) { SearchMatch match = newDeclarationMatch(pkg, null/*no binding*/, SearchMatch.A_ACCURATE, -1, -1); @@ -1373,6 +1367,47 @@ return newTypeReferenceMatch(enclosingElement, enclosingBinding, accuracy, reference.sourceStart, reference.sourceEnd-reference.sourceStart+1, reference); } +/** + * Add the possibleMatch to the loop + * -> build compilation unit declarations, their bindings and record their results. + */ +protected boolean parseAndBuildBindings(PossibleMatch possibleMatch, boolean mustResolve) throws CoreException { + if (this.progressMonitor != null && this.progressMonitor.isCanceled()) + throw new OperationCanceledException(); + + try { + if (BasicSearchEngine.VERBOSE) + System.out.println("Parsing " + possibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$ + + this.parser.nodeSet = possibleMatch.nodeSet; + CompilationResult unitResult = new CompilationResult(possibleMatch, 1, 1, this.options.maxProblemsPerUnit); + CompilationUnitDeclaration parsedUnit = this.parser.dietParse(possibleMatch, unitResult); + if (parsedUnit != null) { + if (!parsedUnit.isEmpty()) { + if (mustResolve) { + this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); + } + if (hasAlreadyDefinedType(parsedUnit)) return false; // skip type has it is hidden so not visible + getMethodBodies(parsedUnit, possibleMatch.nodeSet); + if (this.patternLocator.mayBeGeneric && !mustResolve && possibleMatch.nodeSet.mustResolve) { + // special case: possible match node set force resolution although pattern does not + // => we need to build types for this compilation unit + this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); + } + } + + // add the possibleMatch with its parsedUnit to matchesToProcess + possibleMatch.parsedUnit = parsedUnit; + int size = this.matchesToProcess.length; + if (this.numberOfMatches == size) + System.arraycopy(this.matchesToProcess, 0, this.matchesToProcess = new PossibleMatch[size == 0 ? 1 : size * 2], 0, this.numberOfMatches); + this.matchesToProcess[this.numberOfMatches++] = possibleMatch; + } + } finally { + this.parser.nodeSet = null; + } + return true; +} /* * Process a compilation unit already parsed and build. */ @@ -1391,9 +1426,10 @@ } if (hasAlreadyDefinedType(unit)) return; // skip type has it is hidden so not visible - getMethodBodies(unit); + // Move getMethodBodies to #parseAndBuildings(...) method to allow possible match resolution management + //getMethodBodies(unit); - boolean mustResolve = ((InternalSearchPattern)this.pattern).mustResolve; + boolean mustResolve = ((InternalSearchPattern)this.pattern).mustResolve || possibleMatch.nodeSet.mustResolve; if (bindingsWereCreated && mustResolve) { if (unit.types != null) { if (BasicSearchEngine.VERBOSE) @@ -1773,7 +1809,7 @@ if (encloses(enclosingElement)) { int length = scanner.currentPosition - nameSourceStart; SearchMatch match = this.patternLocator.newDeclarationMatch(method, enclosingElement, method.binding, accuracy, length, this); - report(match); + if (match != null) report(match); } } } @@ -1868,6 +1904,8 @@ */ protected void reportMatching(CompilationUnitDeclaration unit, boolean mustResolve) throws CoreException { MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet; + boolean locatorMustResolve = this.patternLocator.mustResolve; + if (nodeSet.mustResolve) this.patternLocator.mustResolve = true; if (mustResolve) { this.unitScope= unit.scope.compilationUnitScope(); // move the possible matching nodes that exactly match the search pattern to the matching nodes set @@ -1950,6 +1988,8 @@ // Clear handle cache this.methodHandles = null; + this.bindings.removeKey(this.pattern); + this.patternLocator.mustResolve = locatorMustResolve; } /** * Visit the given field declaration and report the nodes that match exactly the Index: search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java,v retrieving revision 1.29 diff -u -r1.29 MatchingNodeSet.java --- search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java 23 Feb 2005 02:47:46 -0000 1.29 +++ search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java 8 Jun 2005 14:36:15 -0000 @@ -36,12 +36,23 @@ static Integer ERASURE_MATCH = new Integer(SearchPattern.R_ERASURE_MATCH); /** + * Tell whether locators need to resolve or not for current matching node set. + */ +public boolean mustResolve; + +/** * Set of possible matching ast nodes. They need to be resolved * to determine if they really match the search pattern. */ SimpleSet possibleMatchingNodesSet = new SimpleSet(7); private HashtableOfLong possibleMatchingNodesKeys = new HashtableOfLong(7); + +public MatchingNodeSet(boolean mustResolvePattern) { + super(); + mustResolve = mustResolvePattern; +} + public int addMatch(ASTNode node, int matchLevel) { switch (matchLevel) { case PatternLocator.INACCURATE_MATCH: Index: search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java,v retrieving revision 1.53 diff -u -r1.53 MethodLocator.java --- search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java 6 Jun 2005 08:09:08 -0000 1.53 +++ search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java 8 Jun 2005 14:36:16 -0000 @@ -49,6 +49,64 @@ // inaccurate matches will be found } } +/* + * Return whether a method may override a method in super classes erasures or not. + */ +private boolean isErasureMethodOverride(ReferenceBinding type, MethodBinding method) { + if (type == null) return false; + + // matches superclass + if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) { + ReferenceBinding superClass = type.superclass(); + if (superClass.isParameterizedType()) { + TypeBinding erasure = ((ParameterizedTypeBinding)superClass).erasure(); + if (erasure instanceof ReferenceBinding) { + MethodBinding[] methods = superClass.getMethods(this.pattern.selector); + int length = methods.length; + for (int i = 0; i newLevel) { if (newLevel == IMPOSSIBLE_MATCH) { -// if (isErasureMatch) { -// return ERASURE_MATCH; -// } - return IMPOSSIBLE_MATCH; + if (skipImpossibleArg) { + // Do not consider match as impossible while finding declarations and source level >= 1.5 + // (see bugs https://bugs.eclipse.org/bugs/show_bug.cgi?id=79990, 96761, 96763) + newLevel = level; + } else { + return IMPOSSIBLE_MATCH; + } } level = newLevel; // can only be downgraded } @@ -218,54 +283,6 @@ return level; } /** - * Return if pattern method may override a method in super classes - * or or implement one in super interfaces of given type. - * @param type - * @return level - */ -int matchOverriddenMethod(ReferenceBinding type) { - if (type == null) return INACCURATE_MATCH; - int level = IMPOSSIBLE_MATCH; - - // matches superclass - if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) { - if (type.superclass().isParameterizedType()) { - TypeBinding erasure = ((ParameterizedTypeBinding)type.superclass()).erasure(); - if (erasure instanceof ReferenceBinding) { - MethodBinding[] methods = ((ReferenceBinding)erasure).getMethods(this.pattern.selector); - int length = methods.length; - for (int i = 0; i 0) { - int psLength = parameterSimpleNames.length; - try { - // Currently, we need to resolve for generic if one of method type argument - // equals to one of declaring type type parameter - ITypeParameter[] typeParameters = this.declaringType.getTypeParameters(); - if (typeParameters != null && typeParameters.length > 0) { - int tpLength = typeParameters.length; - for (int i=0; i