Source Code Cross Referenced for MethodLocator.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » core » search » matching » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » jdt » org.eclipse.jdt.internal.core.search.matching 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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 java.util.HashMap;
013:
014:        import org.eclipse.core.resources.IResource;
015:        import org.eclipse.core.runtime.*;
016:        import org.eclipse.jdt.core.*;
017:        import org.eclipse.jdt.core.compiler.CharOperation;
018:        import org.eclipse.jdt.core.search.*;
019:        import org.eclipse.jdt.internal.compiler.ast.*;
020:        import org.eclipse.jdt.internal.compiler.env.IBinaryType;
021:        import org.eclipse.jdt.internal.compiler.lookup.*;
022:        import org.eclipse.jdt.internal.compiler.util.SimpleSet;
023:        import org.eclipse.jdt.internal.core.JavaElement;
024:        import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
025:
026:        public class MethodLocator extends PatternLocator {
027:
028:            protected MethodPattern pattern;
029:            protected boolean isDeclarationOfReferencedMethodsPattern;
030:
031:            //extra reference info
032:            public char[][][] allSuperDeclaringTypeNames;
033:
034:            //method declarations which parameters verification fail
035:            private HashMap methodDeclarationsWithInvalidParam = new HashMap();
036:
037:            public MethodLocator(MethodPattern pattern) {
038:                super (pattern);
039:
040:                this .pattern = pattern;
041:                this .isDeclarationOfReferencedMethodsPattern = this .pattern instanceof  DeclarationOfReferencedMethodsPattern;
042:            }
043:
044:            /*
045:             * Clear caches
046:             */
047:            protected void clear() {
048:                this .methodDeclarationsWithInvalidParam = new HashMap();
049:            }
050:
051:            public void initializePolymorphicSearch(MatchLocator locator) {
052:                long start = 0;
053:                if (BasicSearchEngine.VERBOSE) {
054:                    start = System.currentTimeMillis();
055:                }
056:                try {
057:                    this .allSuperDeclaringTypeNames = new SuperTypeNamesCollector(
058:                            this .pattern, this .pattern.declaringSimpleName,
059:                            this .pattern.declaringQualification, locator,
060:                            this .pattern.declaringType, locator.progressMonitor)
061:                            .collect();
062:                } catch (JavaModelException e) {
063:                    // inaccurate matches will be found
064:                }
065:                if (BasicSearchEngine.VERBOSE) {
066:                    System.out
067:                            .println("Time to initialize polymorphic search: " + (System.currentTimeMillis() - start)); //$NON-NLS-1$
068:                }
069:            }
070:
071:            /*
072:             * Return whether a type name is in pattern all super declaring types names.
073:             */
074:            private boolean isTypeInSuperDeclaringTypeNames(char[][] typeName) {
075:                if (allSuperDeclaringTypeNames == null)
076:                    return false;
077:                int length = allSuperDeclaringTypeNames.length;
078:                for (int i = 0; i < length; i++) {
079:                    if (CharOperation.equals(allSuperDeclaringTypeNames[i],
080:                            typeName)) {
081:                        return true;
082:                    }
083:                }
084:                return false;
085:            }
086:
087:            /**
088:             * Returns whether the code gen will use an invoke virtual for 
089:             * this message send or not.
090:             */
091:            protected boolean isVirtualInvoke(MethodBinding method,
092:                    MessageSend messageSend) {
093:                return !method.isStatic() && !method.isPrivate()
094:                        && !messageSend.isSuperAccess();
095:            }
096:
097:            public int match(ASTNode node, MatchingNodeSet nodeSet) {
098:                int declarationsLevel = IMPOSSIBLE_MATCH;
099:                if (this .pattern.findReferences) {
100:                    if (node instanceof  ImportReference) {
101:                        // With static import, we can have static method reference in import reference
102:                        ImportReference importRef = (ImportReference) node;
103:                        int length = importRef.tokens.length - 1;
104:                        if (importRef.isStatic()
105:                                && ((importRef.bits & ASTNode.OnDemand) == 0)
106:                                && matchesName(this .pattern.selector,
107:                                        importRef.tokens[length])) {
108:                            char[][] compoundName = new char[length][];
109:                            System.arraycopy(importRef.tokens, 0, compoundName,
110:                                    0, length);
111:                            char[] declaringType = CharOperation.concat(
112:                                    pattern.declaringQualification,
113:                                    pattern.declaringSimpleName, '.');
114:                            if (matchesName(declaringType, CharOperation
115:                                    .concatWith(compoundName, '.'))) {
116:                                declarationsLevel = ((InternalSearchPattern) this .pattern).mustResolve ? POSSIBLE_MATCH
117:                                        : ACCURATE_MATCH;
118:                            }
119:                        }
120:                    }
121:                }
122:                return nodeSet.addMatch(node, declarationsLevel);
123:            }
124:
125:            //public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
126:            //public int match(Expression node, MatchingNodeSet nodeSet) - SKIP IT
127:            //public int match(FieldDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
128:            public int match(MethodDeclaration node, MatchingNodeSet nodeSet) {
129:                if (!this .pattern.findDeclarations)
130:                    return IMPOSSIBLE_MATCH;
131:
132:                // Verify method name
133:                if (!matchesName(this .pattern.selector, node.selector))
134:                    return IMPOSSIBLE_MATCH;
135:
136:                // Verify parameters types
137:                boolean resolve = ((InternalSearchPattern) this .pattern).mustResolve;
138:                if (this .pattern.parameterSimpleNames != null) {
139:                    int length = this .pattern.parameterSimpleNames.length;
140:                    ASTNode[] args = node.arguments;
141:                    int argsLength = args == null ? 0 : args.length;
142:                    if (length != argsLength)
143:                        return IMPOSSIBLE_MATCH;
144:                    for (int i = 0; i < argsLength; i++) {
145:                        if (args != null
146:                                && !matchesTypeReference(
147:                                        this .pattern.parameterSimpleNames[i],
148:                                        ((Argument) args[i]).type)) {
149:                            // Do not return as impossible when source level is at least 1.5
150:                            if (this .mayBeGeneric) {
151:                                if (!((InternalSearchPattern) this .pattern).mustResolve) {
152:                                    // Set resolution flag on node set in case of types was inferred in parameterized types from generic ones...
153:                                    // (see  bugs https://bugs.eclipse.org/bugs/show_bug.cgi?id=79990, 96761, 96763)
154:                                    nodeSet.mustResolve = true;
155:                                    resolve = true;
156:                                }
157:                                this .methodDeclarationsWithInvalidParam.put(
158:                                        node, null);
159:                            } else {
160:                                return IMPOSSIBLE_MATCH;
161:                            }
162:                        }
163:                    }
164:                }
165:
166:                // Verify type arguments (do not reject if pattern has no argument as it can be an erasure match)
167:                if (this .pattern.hasMethodArguments()) {
168:                    if (node.typeParameters == null
169:                            || node.typeParameters.length != this .pattern.methodArguments.length)
170:                        return IMPOSSIBLE_MATCH;
171:                }
172:
173:                // Method declaration may match pattern
174:                return nodeSet.addMatch(node, resolve ? POSSIBLE_MATCH
175:                        : ACCURATE_MATCH);
176:            }
177:
178:            public int match(MemberValuePair node, MatchingNodeSet nodeSet) {
179:                if (!this .pattern.findReferences)
180:                    return IMPOSSIBLE_MATCH;
181:
182:                if (!matchesName(this .pattern.selector, node.name))
183:                    return IMPOSSIBLE_MATCH;
184:
185:                return nodeSet
186:                        .addMatch(
187:                                node,
188:                                ((InternalSearchPattern) this .pattern).mustResolve ? POSSIBLE_MATCH
189:                                        : ACCURATE_MATCH);
190:            }
191:
192:            public int match(MessageSend node, MatchingNodeSet nodeSet) {
193:                if (!this .pattern.findReferences)
194:                    return IMPOSSIBLE_MATCH;
195:
196:                if (!matchesName(this .pattern.selector, node.selector))
197:                    return IMPOSSIBLE_MATCH;
198:                if (this .pattern.parameterSimpleNames != null
199:                        && (!this .pattern.varargs || ((node.bits & ASTNode.InsideJavadoc) != 0))) {
200:                    int length = this .pattern.parameterSimpleNames.length;
201:                    ASTNode[] args = node.arguments;
202:                    int argsLength = args == null ? 0 : args.length;
203:                    if (length != argsLength)
204:                        return IMPOSSIBLE_MATCH;
205:                }
206:
207:                return nodeSet
208:                        .addMatch(
209:                                node,
210:                                ((InternalSearchPattern) this .pattern).mustResolve ? POSSIBLE_MATCH
211:                                        : ACCURATE_MATCH);
212:            }
213:
214:            //public int match(Reference node, MatchingNodeSet nodeSet) - SKIP IT
215:            public int match(Annotation node, MatchingNodeSet nodeSet) {
216:                if (!this .pattern.findReferences)
217:                    return IMPOSSIBLE_MATCH;
218:                MemberValuePair[] pairs = node.memberValuePairs();
219:                if (pairs == null || pairs.length == 0)
220:                    return IMPOSSIBLE_MATCH;
221:
222:                int length = pairs.length;
223:                MemberValuePair pair = null;
224:                for (int i = 0; i < length; i++) {
225:                    pair = node.memberValuePairs()[i];
226:                    if (matchesName(this .pattern.selector, pair.name)) {
227:                        ASTNode possibleNode = (node instanceof  SingleMemberAnnotation) ? (ASTNode) node
228:                                : pair;
229:                        return nodeSet
230:                                .addMatch(
231:                                        possibleNode,
232:                                        ((InternalSearchPattern) this .pattern).mustResolve ? POSSIBLE_MATCH
233:                                                : ACCURATE_MATCH);
234:                    }
235:                }
236:                return IMPOSSIBLE_MATCH;
237:            }
238:
239:            //public int match(TypeDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
240:            //public int match(TypeReference node, MatchingNodeSet nodeSet) - SKIP IT
241:
242:            protected int matchContainer() {
243:                if (this .pattern.findReferences) {
244:                    // need to look almost everywhere to find in javadocs and static import
245:                    return ALL_CONTAINER;
246:                }
247:                return CLASS_CONTAINER;
248:            }
249:
250:            /* (non-Javadoc)
251:             * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchLevelAndReportImportRef(org.eclipse.jdt.internal.compiler.ast.ImportReference, org.eclipse.jdt.internal.compiler.lookup.Binding, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
252:             * Accept to report match of static field on static import
253:             */
254:            protected void matchLevelAndReportImportRef(
255:                    ImportReference importRef, Binding binding,
256:                    MatchLocator locator) throws CoreException {
257:                if (importRef.isStatic() && binding instanceof  MethodBinding) {
258:                    super .matchLevelAndReportImportRef(importRef, binding,
259:                            locator);
260:                }
261:            }
262:
263:            protected int matchMethod(MethodBinding method,
264:                    boolean skipImpossibleArg) {
265:                if (!matchesName(this .pattern.selector, method.selector))
266:                    return IMPOSSIBLE_MATCH;
267:
268:                int level = ACCURATE_MATCH;
269:                // look at return type only if declaring type is not specified
270:                if (this .pattern.declaringSimpleName == null) {
271:                    // TODO (frederic) use this call to refine accuracy on return type
272:                    // int newLevel = resolveLevelForType(this.pattern.returnSimpleName, this.pattern.returnQualification, this.pattern.returnTypeArguments, 0, method.returnType);
273:                    int newLevel = resolveLevelForType(
274:                            this .pattern.returnSimpleName,
275:                            this .pattern.returnQualification, method.returnType);
276:                    if (level > newLevel) {
277:                        if (newLevel == IMPOSSIBLE_MATCH)
278:                            return IMPOSSIBLE_MATCH;
279:                        level = newLevel; // can only be downgraded
280:                    }
281:                }
282:
283:                // parameter types
284:                int parameterCount = this .pattern.parameterSimpleNames == null ? -1
285:                        : this .pattern.parameterSimpleNames.length;
286:                if (parameterCount > -1) {
287:                    // global verification
288:                    if (method.parameters == null)
289:                        return INACCURATE_MATCH;
290:                    if (parameterCount != method.parameters.length)
291:                        return IMPOSSIBLE_MATCH;
292:                    if (!method.isValidBinding()
293:                            && ((ProblemMethodBinding) method).problemId() == ProblemReasons.Ambiguous) {
294:                        // return inaccurate match for ambiguous call (bug 80890)
295:                        return INACCURATE_MATCH;
296:                    }
297:
298:                    // verify each parameter
299:                    for (int i = 0; i < parameterCount; i++) {
300:                        TypeBinding argType = method.parameters[i];
301:                        int newLevel = IMPOSSIBLE_MATCH;
302:                        if (argType.isMemberType()) {
303:                            // only compare source name for member type (bug 41018)
304:                            newLevel = CharOperation.match(
305:                                    this .pattern.parameterSimpleNames[i],
306:                                    argType.sourceName(), this .isCaseSensitive) ? ACCURATE_MATCH
307:                                    : IMPOSSIBLE_MATCH;
308:                        } else {
309:                            // TODO (frederic) use this call to refine accuracy on parameter types
310:                            //				 newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], this.pattern.parametersTypeArguments[i], 0, argType);
311:                            newLevel = resolveLevelForType(
312:                                    this .pattern.parameterSimpleNames[i],
313:                                    this .pattern.parameterQualifications[i],
314:                                    argType);
315:                        }
316:                        if (level > newLevel) {
317:                            if (newLevel == IMPOSSIBLE_MATCH) {
318:                                if (skipImpossibleArg) {
319:                                    // Do not consider match as impossible while finding declarations and source level >= 1.5
320:                                    // (see  bugs https://bugs.eclipse.org/bugs/show_bug.cgi?id=79990, 96761, 96763)
321:                                    newLevel = level;
322:                                } else {
323:                                    return IMPOSSIBLE_MATCH;
324:                                }
325:                            }
326:                            level = newLevel; // can only be downgraded
327:                        }
328:                    }
329:                }
330:
331:                return level;
332:            }
333:
334:            private boolean matchOverriddenMethod(ReferenceBinding type,
335:                    MethodBinding method, MethodBinding matchMethod) {
336:                if (type == null || this .pattern.selector == null)
337:                    return false;
338:
339:                // matches superclass
340:                if (!type.isInterface()
341:                        && !CharOperation.equals(type.compoundName,
342:                                TypeConstants.JAVA_LANG_OBJECT)) {
343:                    ReferenceBinding super Class = type.super class();
344:                    if (super Class.isParameterizedType()) {
345:                        MethodBinding[] methods = super Class
346:                                .getMethods(this .pattern.selector);
347:                        int length = methods.length;
348:                        for (int i = 0; i < length; i++) {
349:                            if (methods[i].areParametersEqual(method)) {
350:                                if (matchMethod == null) {
351:                                    if (methodParametersEqualsPattern(methods[i]
352:                                            .original()))
353:                                        return true;
354:                                } else {
355:                                    if (methods[i].original()
356:                                            .areParametersEqual(matchMethod))
357:                                        return true;
358:                                }
359:                            }
360:                        }
361:                    }
362:                    if (matchOverriddenMethod(super Class, method, matchMethod)) {
363:                        return true;
364:                    }
365:                }
366:
367:                // matches interfaces
368:                ReferenceBinding[] interfaces = type.super Interfaces();
369:                if (interfaces == null)
370:                    return false;
371:                int iLength = interfaces.length;
372:                for (int i = 0; i < iLength; i++) {
373:                    if (interfaces[i].isParameterizedType()) {
374:                        MethodBinding[] methods = interfaces[i]
375:                                .getMethods(this .pattern.selector);
376:                        int length = methods.length;
377:                        for (int j = 0; j < length; j++) {
378:                            if (methods[j].areParametersEqual(method)) {
379:                                if (matchMethod == null) {
380:                                    if (methodParametersEqualsPattern(methods[j]
381:                                            .original()))
382:                                        return true;
383:                                } else {
384:                                    if (methods[j].original()
385:                                            .areParametersEqual(matchMethod))
386:                                        return true;
387:                                }
388:                            }
389:                        }
390:                    }
391:                    if (matchOverriddenMethod(interfaces[i], method,
392:                            matchMethod)) {
393:                        return true;
394:                    }
395:                }
396:                return false;
397:            }
398:
399:            /**
400:             * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchReportReference(org.eclipse.jdt.internal.compiler.ast.ASTNode, org.eclipse.jdt.core.IJavaElement, Binding, int, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
401:             */
402:            protected void matchReportReference(ASTNode reference,
403:                    IJavaElement element, Binding elementBinding, int accuracy,
404:                    MatchLocator locator) throws CoreException {
405:                MethodBinding methodBinding = (reference instanceof  MessageSend) ? ((MessageSend) reference).binding
406:                        : ((elementBinding instanceof  MethodBinding) ? (MethodBinding) elementBinding
407:                                : null);
408:                if (this .isDeclarationOfReferencedMethodsPattern) {
409:                    if (methodBinding == null)
410:                        return;
411:                    // need exact match to be able to open on type ref
412:                    if (accuracy != SearchMatch.A_ACCURATE)
413:                        return;
414:
415:                    // element that references the method must be included in the enclosing element
416:                    DeclarationOfReferencedMethodsPattern declPattern = (DeclarationOfReferencedMethodsPattern) this .pattern;
417:                    while (element != null
418:                            && !declPattern.enclosingElement.equals(element))
419:                        element = element.getParent();
420:                    if (element != null) {
421:                        reportDeclaration(methodBinding, locator,
422:                                declPattern.knownMethods);
423:                    }
424:                } else {
425:                    match = locator.newMethodReferenceMatch(element,
426:                            elementBinding, accuracy, -1, -1,
427:                            false /*not constructor*/,
428:                            false/*not synthetic*/, reference);
429:                    if (this .pattern.findReferences
430:                            && reference instanceof  MessageSend) {
431:                        IJavaElement focus = ((InternalSearchPattern) this .pattern).focus;
432:                        // verify closest match if pattern was bound
433:                        // (see bug 70827)
434:                        if (focus != null
435:                                && focus.getElementType() == IJavaElement.METHOD) {
436:                            if (methodBinding != null
437:                                    && methodBinding.declaringClass != null) {
438:                                boolean isPrivate = Flags
439:                                        .isPrivate(((IMethod) focus).getFlags());
440:                                if (isPrivate
441:                                        && !CharOperation
442:                                                .equals(
443:                                                        methodBinding.declaringClass.sourceName,
444:                                                        focus
445:                                                                .getParent()
446:                                                                .getElementName()
447:                                                                .toCharArray())) {
448:                                    return; // finally the match was not possible
449:                                }
450:                            }
451:                        }
452:                        matchReportReference((MessageSend) reference, locator,
453:                                ((MessageSend) reference).binding);
454:                    } else {
455:                        if (reference instanceof  SingleMemberAnnotation) {
456:                            reference = ((SingleMemberAnnotation) reference)
457:                                    .memberValuePairs()[0];
458:                            match.setImplicit(true);
459:                        }
460:                        int offset = reference.sourceStart;
461:                        int length = reference.sourceEnd - offset + 1;
462:                        match.setOffset(offset);
463:                        match.setLength(length);
464:                        locator.report(match);
465:                    }
466:                }
467:            }
468:
469:            void matchReportReference(MessageSend messageSend,
470:                    MatchLocator locator, MethodBinding methodBinding)
471:                    throws CoreException {
472:
473:                // Look if there's a need to special report for parameterized type
474:                boolean isParameterized = false;
475:                if (methodBinding instanceof  ParameterizedGenericMethodBinding) { // parameterized generic method
476:                    isParameterized = true;
477:
478:                    // Update match regarding method type arguments
479:                    ParameterizedGenericMethodBinding parameterizedMethodBinding = (ParameterizedGenericMethodBinding) methodBinding;
480:                    match.setRaw(parameterizedMethodBinding.isRaw);
481:                    TypeBinding[] typeArguments = /*parameterizedMethodBinding.isRaw ? null :*/parameterizedMethodBinding.typeArguments;
482:                    updateMatch(typeArguments, locator,
483:                            this .pattern.methodArguments, this .pattern
484:                                    .hasMethodParameters());
485:
486:                    // Update match regarding declaring class type arguments
487:                    if (methodBinding.declaringClass.isParameterizedType()
488:                            || methodBinding.declaringClass.isRawType()) {
489:                        ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding) methodBinding.declaringClass;
490:                        if (!this .pattern.hasTypeArguments()
491:                                && this .pattern.hasMethodArguments()
492:                                || parameterizedBinding
493:                                        .isParameterizedWithOwnVariables()) {
494:                            // special case for pattern which defines method arguments but not its declaring type
495:                            // in this case, we do not refine accuracy using declaring type arguments...!
496:                        } else {
497:                            updateMatch(parameterizedBinding, this .pattern
498:                                    .getTypeArguments(), this .pattern
499:                                    .hasTypeParameters(), 0, locator);
500:                        }
501:                    } else if (this .pattern.hasTypeArguments()) {
502:                        match.setRule(SearchPattern.R_ERASURE_MATCH);
503:                    }
504:
505:                    // Update match regarding method parameters
506:                    // TODO ? (frederic)
507:
508:                    // Update match regarding method return type
509:                    // TODO ? (frederic)
510:
511:                    // Special case for errors
512:                    if (match.getRule() != 0
513:                            && messageSend.resolvedType == null) {
514:                        match.setRule(SearchPattern.R_ERASURE_MATCH);
515:                    }
516:                } else if (methodBinding instanceof  ParameterizedMethodBinding) {
517:                    isParameterized = true;
518:                    if (methodBinding.declaringClass.isParameterizedType()
519:                            || methodBinding.declaringClass.isRawType()) {
520:                        ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding) methodBinding.declaringClass;
521:                        if (!parameterizedBinding
522:                                .isParameterizedWithOwnVariables()) {
523:                            updateMatch(parameterizedBinding, this .pattern
524:                                    .getTypeArguments(), this .pattern
525:                                    .hasTypeParameters(), 0, locator);
526:                        }
527:                    } else if (this .pattern.hasTypeArguments()) {
528:                        match.setRule(SearchPattern.R_ERASURE_MATCH);
529:                    }
530:
531:                    // Update match regarding method parameters
532:                    // TODO ? (frederic)
533:
534:                    // Update match regarding method return type
535:                    // TODO ? (frederic)
536:
537:                    // Special case for errors
538:                    if (match.getRule() != 0
539:                            && messageSend.resolvedType == null) {
540:                        match.setRule(SearchPattern.R_ERASURE_MATCH);
541:                    }
542:                } else if (this .pattern.hasMethodArguments()) { // binding has no type params, compatible erasure if pattern does
543:                    match.setRule(SearchPattern.R_ERASURE_MATCH);
544:                }
545:
546:                // See whether it is necessary to report or not
547:                if (match.getRule() == 0)
548:                    return; // impossible match
549:                boolean report = (this .isErasureMatch && match.isErasure())
550:                        || (this .isEquivalentMatch && match.isEquivalent())
551:                        || match.isExact();
552:                if (!report)
553:                    return;
554:
555:                // Report match
556:                int offset = (int) (messageSend.nameSourcePosition >>> 32);
557:                match.setOffset(offset);
558:                match.setLength(messageSend.sourceEnd - offset + 1);
559:                if (isParameterized && this .pattern.hasMethodArguments()) {
560:                    locator.reportAccurateParameterizedMethodReference(match,
561:                            messageSend, messageSend.typeArguments);
562:                } else {
563:                    locator.report(match);
564:                }
565:            }
566:
567:            /*
568:             * Return whether method parameters are equals to pattern ones.
569:             */
570:            private boolean methodParametersEqualsPattern(MethodBinding method) {
571:                TypeBinding[] methodParameters = method.parameters;
572:
573:                int length = methodParameters.length;
574:                if (length != this .pattern.parameterSimpleNames.length)
575:                    return false;
576:
577:                for (int i = 0; i < length; i++) {
578:                    char[] paramQualifiedName = qualifiedPattern(
579:                            this .pattern.parameterSimpleNames[i],
580:                            this .pattern.parameterQualifications[i]);
581:                    if (!CharOperation.match(paramQualifiedName,
582:                            methodParameters[i].readableName(),
583:                            this .isCaseSensitive)) {
584:                        return false;
585:                    }
586:                }
587:                return true;
588:            }
589:
590:            public SearchMatch newDeclarationMatch(ASTNode reference,
591:                    IJavaElement element, Binding elementBinding, int accuracy,
592:                    int length, MatchLocator locator) {
593:                if (elementBinding != null) {
594:                    MethodBinding methodBinding = (MethodBinding) elementBinding;
595:                    // If method parameters verification was not valid, then try to see if method arguments can match a method in hierarchy
596:                    if (this .methodDeclarationsWithInvalidParam
597:                            .containsKey(reference)) {
598:                        // First see if this reference has already been resolved => report match if validated
599:                        Boolean report = (Boolean) this .methodDeclarationsWithInvalidParam
600:                                .get(reference);
601:                        if (report != null) {
602:                            if (report.booleanValue()) {
603:                                return super .newDeclarationMatch(reference,
604:                                        element, elementBinding, accuracy,
605:                                        length, locator);
606:                            }
607:                            return null;
608:                        }
609:                        if (matchOverriddenMethod(methodBinding.declaringClass,
610:                                methodBinding, null)) {
611:                            this .methodDeclarationsWithInvalidParam.put(
612:                                    reference, Boolean.TRUE);
613:                            return super .newDeclarationMatch(reference,
614:                                    element, elementBinding, accuracy, length,
615:                                    locator);
616:                        }
617:                        if (isTypeInSuperDeclaringTypeNames(methodBinding.declaringClass.compoundName)) {
618:                            MethodBinding patternBinding = locator
619:                                    .getMethodBinding(this .pattern);
620:                            if (patternBinding != null) {
621:                                if (!matchOverriddenMethod(
622:                                        patternBinding.declaringClass,
623:                                        patternBinding, methodBinding)) {
624:                                    this .methodDeclarationsWithInvalidParam
625:                                            .put(reference, Boolean.FALSE);
626:                                    return null;
627:                                }
628:                            }
629:                            this .methodDeclarationsWithInvalidParam.put(
630:                                    reference, Boolean.TRUE);
631:                            return super .newDeclarationMatch(reference,
632:                                    element, elementBinding, accuracy, length,
633:                                    locator);
634:                        }
635:                        this .methodDeclarationsWithInvalidParam.put(reference,
636:                                Boolean.FALSE);
637:                        return null;
638:                    }
639:                }
640:                return super .newDeclarationMatch(reference, element,
641:                        elementBinding, accuracy, length, locator);
642:            }
643:
644:            protected int referenceType() {
645:                return IJavaElement.METHOD;
646:            }
647:
648:            protected void reportDeclaration(MethodBinding methodBinding,
649:                    MatchLocator locator, SimpleSet knownMethods)
650:                    throws CoreException {
651:                ReferenceBinding declaringClass = methodBinding.declaringClass;
652:                IType type = locator.lookupType(declaringClass);
653:                if (type == null)
654:                    return; // case of a secondary type
655:
656:                char[] bindingSelector = methodBinding.selector;
657:                boolean isBinary = type.isBinary();
658:                IMethod method = null;
659:                TypeBinding[] parameters = methodBinding.original().parameters;
660:                int parameterLength = parameters.length;
661:                if (isBinary) {
662:                    char[][] parameterTypes = new char[parameterLength][];
663:                    for (int i = 0; i < parameterLength; i++) {
664:                        char[] typeName = parameters[i].qualifiedSourceName();
665:                        for (int j = 0, dim = parameters[i].dimensions(); j < dim; j++) {
666:                            typeName = CharOperation.concat(typeName,
667:                                    new char[] { '[', ']' });
668:                        }
669:                        parameterTypes[i] = typeName;
670:                    }
671:                    method = locator.createBinaryMethodHandle(type,
672:                            methodBinding.selector, parameterTypes);
673:                } else {
674:                    String[] parameterTypes = new String[parameterLength];
675:                    for (int i = 0; i < parameterLength; i++) {
676:                        char[] typeName = parameters[i].shortReadableName();
677:                        if (parameters[i].isMemberType()) {
678:                            typeName = CharOperation.subarray(typeName,
679:                                    CharOperation.indexOf('.', typeName) + 1,
680:                                    typeName.length);
681:                        }
682:                        parameterTypes[i] = Signature.createTypeSignature(
683:                                typeName, false);
684:                    }
685:                    method = type.getMethod(new String(bindingSelector),
686:                            parameterTypes);
687:                }
688:                if (method == null
689:                        || knownMethods.addIfNotIncluded(method) == null)
690:                    return;
691:
692:                IResource resource = type.getResource();
693:                IBinaryType info = null;
694:                if (isBinary) {
695:                    if (resource == null)
696:                        resource = type.getJavaProject().getProject();
697:                    info = locator.getBinaryInfo(
698:                            (org.eclipse.jdt.internal.core.ClassFile) type
699:                                    .getClassFile(), resource);
700:                    locator.reportBinaryMemberDeclaration(resource, method,
701:                            methodBinding, info, SearchMatch.A_ACCURATE);
702:                } else {
703:                    if (declaringClass instanceof  ParameterizedTypeBinding)
704:                        declaringClass = ((ParameterizedTypeBinding) declaringClass)
705:                                .genericType();
706:                    ClassScope scope = ((SourceTypeBinding) declaringClass).scope;
707:                    if (scope != null) {
708:                        TypeDeclaration typeDecl = scope.referenceContext;
709:                        AbstractMethodDeclaration methodDecl = null;
710:                        AbstractMethodDeclaration[] methodDecls = typeDecl.methods;
711:                        for (int i = 0, length = methodDecls.length; i < length; i++) {
712:                            if (CharOperation.equals(bindingSelector,
713:                                    methodDecls[i].selector)) {
714:                                methodDecl = methodDecls[i];
715:                                break;
716:                            }
717:                        }
718:                        if (methodDecl != null) {
719:                            int offset = methodDecl.sourceStart;
720:                            Binding binding = methodDecl.binding;
721:                            if (binding != null)
722:                                method = (IMethod) ((JavaElement) method)
723:                                        .resolved(binding);
724:                            match = new MethodDeclarationMatch(method,
725:                                    SearchMatch.A_ACCURATE, offset,
726:                                    methodDecl.sourceEnd - offset + 1, locator
727:                                            .getParticipant(), resource);
728:                            locator.report(match);
729:                        }
730:                    }
731:                }
732:            }
733:
734:            public int resolveLevel(ASTNode possibleMatchingNode) {
735:                if (this .pattern.findReferences) {
736:                    if (possibleMatchingNode instanceof  MessageSend) {
737:                        return resolveLevel((MessageSend) possibleMatchingNode);
738:                    }
739:                    if (possibleMatchingNode instanceof  SingleMemberAnnotation) {
740:                        SingleMemberAnnotation annotation = (SingleMemberAnnotation) possibleMatchingNode;
741:                        return resolveLevel(annotation.memberValuePairs()[0].binding);
742:                    }
743:                    if (possibleMatchingNode instanceof  MemberValuePair) {
744:                        MemberValuePair memberValuePair = (MemberValuePair) possibleMatchingNode;
745:                        return resolveLevel(memberValuePair.binding);
746:                    }
747:                }
748:                if (this .pattern.findDeclarations) {
749:                    if (possibleMatchingNode instanceof  MethodDeclaration) {
750:                        return resolveLevel(((MethodDeclaration) possibleMatchingNode).binding);
751:                    }
752:                }
753:                return IMPOSSIBLE_MATCH;
754:            }
755:
756:            public int resolveLevel(Binding binding) {
757:                if (binding == null)
758:                    return INACCURATE_MATCH;
759:                if (!(binding instanceof  MethodBinding))
760:                    return IMPOSSIBLE_MATCH;
761:
762:                MethodBinding method = (MethodBinding) binding;
763:                boolean skipVerif = this .pattern.findDeclarations
764:                        && this .mayBeGeneric;
765:                int methodLevel = matchMethod(method, skipVerif);
766:                if (methodLevel == IMPOSSIBLE_MATCH) {
767:                    if (method != method.original())
768:                        methodLevel = matchMethod(method.original(), skipVerif);
769:                    if (methodLevel == IMPOSSIBLE_MATCH) {
770:                        return IMPOSSIBLE_MATCH;
771:                    } else {
772:                        method = method.original();
773:                    }
774:                }
775:
776:                // declaring type
777:                char[] qualifiedPattern = qualifiedPattern(
778:                        this .pattern.declaringSimpleName,
779:                        this .pattern.declaringQualification);
780:                if (qualifiedPattern == null)
781:                    return methodLevel; // since any declaring class will do
782:
783:                boolean subType = !method.isStatic() && !method.isPrivate();
784:                if (subType && this .pattern.declaringQualification != null
785:                        && method.declaringClass != null
786:                        && method.declaringClass.fPackage != null) {
787:                    subType = CharOperation.compareWith(
788:                            this .pattern.declaringQualification,
789:                            method.declaringClass.fPackage.shortReadableName()) == 0;
790:                }
791:                int declaringLevel = subType ? resolveLevelAsSubtype(
792:                        qualifiedPattern, method.declaringClass, null)
793:                        : resolveLevelForType(qualifiedPattern,
794:                                method.declaringClass);
795:                return methodLevel > declaringLevel ? declaringLevel
796:                        : methodLevel; // return the weaker match
797:            }
798:
799:            protected int resolveLevel(MessageSend messageSend) {
800:                MethodBinding method = messageSend.binding;
801:                if (method == null) {
802:                    return INACCURATE_MATCH;
803:                }
804:                if (messageSend.resolvedType == null) {
805:                    // Closest match may have different argument numbers when ProblemReason is NotFound
806:                    // see MessageSend#resolveType(BlockScope)
807:                    // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=97322
808:                    int argLength = messageSend.arguments == null ? 0
809:                            : messageSend.arguments.length;
810:                    if (pattern.parameterSimpleNames == null
811:                            || argLength == pattern.parameterSimpleNames.length) {
812:                        return INACCURATE_MATCH;
813:                    }
814:                    return IMPOSSIBLE_MATCH;
815:                }
816:
817:                int methodLevel = matchMethod(method, false);
818:                if (methodLevel == IMPOSSIBLE_MATCH) {
819:                    if (method != method.original())
820:                        methodLevel = matchMethod(method.original(), false);
821:                    if (methodLevel == IMPOSSIBLE_MATCH)
822:                        return IMPOSSIBLE_MATCH;
823:                    method = method.original();
824:                }
825:
826:                // receiver type
827:                char[] qualifiedPattern = qualifiedPattern(
828:                        this .pattern.declaringSimpleName,
829:                        this .pattern.declaringQualification);
830:                if (qualifiedPattern == null)
831:                    return methodLevel; // since any declaring class will do
832:
833:                int declaringLevel;
834:                if (isVirtualInvoke(method, messageSend)
835:                        && (messageSend.actualReceiverType instanceof  ReferenceBinding)) {
836:                    ReferenceBinding methodReceiverType = (ReferenceBinding) messageSend.actualReceiverType;
837:                    declaringLevel = resolveLevelAsSubtype(qualifiedPattern,
838:                            methodReceiverType, method.parameters);
839:                    if (declaringLevel == IMPOSSIBLE_MATCH) {
840:                        if (method.declaringClass == null
841:                                || this .allSuperDeclaringTypeNames == null) {
842:                            declaringLevel = INACCURATE_MATCH;
843:                        } else {
844:                            char[][] compoundName = methodReceiverType.compoundName;
845:                            for (int i = 0, max = this .allSuperDeclaringTypeNames.length; i < max; i++) {
846:                                if (CharOperation.equals(
847:                                        this .allSuperDeclaringTypeNames[i],
848:                                        compoundName)) {
849:                                    return methodLevel // since this is an ACCURATE_MATCH so return the possibly weaker match
850:                                            | SUPER_INVOCATION_FLAVOR; // this is an overridden method => add flavor to returned level
851:                                }
852:                            }
853:                            /* Do not return interfaces potential matches
854:                             * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=157814#c8"
855:                            if (methodReceiverType.isInterface()) {
856:                            	// all methods interface with same name and parameters are potential matches
857:                            	// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=156491
858:                            	return INACCURATE_MATCH | POLYMORPHIC_FLAVOR;
859:                            }
860:                             */
861:                        }
862:                    }
863:                    if ((declaringLevel & FLAVORS_MASK) != 0) {
864:                        // level got some flavors => return it
865:                        return declaringLevel;
866:                    }
867:                } else {
868:                    declaringLevel = resolveLevelForType(qualifiedPattern,
869:                            method.declaringClass);
870:                }
871:                return methodLevel > declaringLevel ? declaringLevel
872:                        : methodLevel; // return the weaker match
873:            }
874:
875:            /**
876:             * Returns whether the given reference type binding matches or is a subtype of a type
877:             * that matches the given qualified pattern.
878:             * Returns ACCURATE_MATCH if it does.
879:             * Returns INACCURATE_MATCH if resolve fails
880:             * Returns IMPOSSIBLE_MATCH if it doesn't.
881:             */
882:            protected int resolveLevelAsSubtype(char[] qualifiedPattern,
883:                    ReferenceBinding type, TypeBinding[] argumentTypes) {
884:                if (type == null)
885:                    return INACCURATE_MATCH;
886:
887:                int level = resolveLevelForType(qualifiedPattern, type);
888:                if (level != IMPOSSIBLE_MATCH) {
889:                    if (!type.isAbstract() && !type.isInterface()) { // if concrete class, then method is overridden
890:                        level |= OVERRIDDEN_METHOD_FLAVOR;
891:                    }
892:                    return level;
893:                }
894:
895:                // matches superclass
896:                if (!type.isInterface()
897:                        && !CharOperation.equals(type.compoundName,
898:                                TypeConstants.JAVA_LANG_OBJECT)) {
899:                    level = resolveLevelAsSubtype(qualifiedPattern, type
900:                            .super class(), argumentTypes);
901:                    if (level != IMPOSSIBLE_MATCH) {
902:                        if (argumentTypes != null) {
903:                            // need to verify if method may be overridden
904:                            MethodBinding[] methods = type
905:                                    .getMethods(this .pattern.selector);
906:                            for (int i = 0, length = methods.length; i < length; i++) {
907:                                MethodBinding method = methods[i];
908:                                TypeBinding[] parameters = method.parameters;
909:                                if (argumentTypes.length == parameters.length) {
910:                                    boolean found = true;
911:                                    for (int j = 0, l = parameters.length; j < l; j++) {
912:                                        if (parameters[j].erasure() != argumentTypes[j]
913:                                                .erasure()) {
914:                                            found = false;
915:                                            break;
916:                                        }
917:                                    }
918:                                    if (found) { // one method match in hierarchy
919:                                        if ((level & OVERRIDDEN_METHOD_FLAVOR) != 0) {
920:                                            // this method is already overridden on a super class, current match is impossible
921:                                            return IMPOSSIBLE_MATCH;
922:                                        }
923:                                        if (!method.isAbstract()
924:                                                && !type.isInterface()) {
925:                                            // store the fact that the method is overridden
926:                                            level |= OVERRIDDEN_METHOD_FLAVOR;
927:                                        }
928:                                    }
929:                                }
930:                            }
931:                        }
932:                        return level | SUB_INVOCATION_FLAVOR; // add flavor to returned level
933:                    }
934:                }
935:
936:                // matches interfaces
937:                ReferenceBinding[] interfaces = type.super Interfaces();
938:                if (interfaces == null)
939:                    return INACCURATE_MATCH;
940:                for (int i = 0; i < interfaces.length; i++) {
941:                    level = resolveLevelAsSubtype(qualifiedPattern,
942:                            interfaces[i], null);
943:                    if (level != IMPOSSIBLE_MATCH) {
944:                        if (!type.isAbstract() && !type.isInterface()) { // if concrete class, then method is overridden
945:                            level |= OVERRIDDEN_METHOD_FLAVOR;
946:                        }
947:                        return level | SUB_INVOCATION_FLAVOR; // add flavor to returned level
948:                    }
949:                }
950:                return IMPOSSIBLE_MATCH;
951:            }
952:
953:            public String toString() {
954:                return "Locator for " + this .pattern.toString(); //$NON-NLS-1$
955:            }
956:        }
w___ww__.__j___a_v__a__2_s__.com_ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.