Source Code Cross Referenced for MatchLocator.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) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *******************************************************************************/package org.eclipse.jdt.internal.core.search.matching;
0011:
0012:        import java.io.IOException;
0013:        import java.util.ArrayList;
0014:        import java.util.HashMap;
0015:        import java.util.HashSet;
0016:        import java.util.Iterator;
0017:        import java.util.Map;
0018:        import java.util.zip.ZipFile;
0019:
0020:        import org.eclipse.core.resources.IResource;
0021:        import org.eclipse.core.runtime.*;
0022:        import org.eclipse.jdt.core.Flags;
0023:        import org.eclipse.jdt.core.IClassFile;
0024:        import org.eclipse.jdt.core.IJavaElement;
0025:        import org.eclipse.jdt.core.IJavaModelStatusConstants;
0026:        import org.eclipse.jdt.core.IJavaProject;
0027:        import org.eclipse.jdt.core.IMember;
0028:        import org.eclipse.jdt.core.IMethod;
0029:        import org.eclipse.jdt.core.IPackageFragment;
0030:        import org.eclipse.jdt.core.IPackageFragmentRoot;
0031:        import org.eclipse.jdt.core.ISourceRange;
0032:        import org.eclipse.jdt.core.IType;
0033:        import org.eclipse.jdt.core.JavaModelException;
0034:        import org.eclipse.jdt.core.Signature;
0035:        import org.eclipse.jdt.core.compiler.*;
0036:        import org.eclipse.jdt.core.search.*;
0037:        import org.eclipse.jdt.internal.compiler.ASTVisitor;
0038:        import org.eclipse.jdt.internal.compiler.CompilationResult;
0039:        import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
0040:        import org.eclipse.jdt.internal.compiler.ast.*;
0041:        import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
0042:        import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
0043:        import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
0044:        import org.eclipse.jdt.internal.compiler.env.*;
0045:        import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
0046:        import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
0047:        import org.eclipse.jdt.internal.compiler.lookup.*;
0048:        import org.eclipse.jdt.internal.compiler.parser.*;
0049:        import org.eclipse.jdt.internal.compiler.problem.*;
0050:        import org.eclipse.jdt.internal.compiler.util.HashtableOfIntValues;
0051:        import org.eclipse.jdt.internal.compiler.util.Messages;
0052:        import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
0053:        import org.eclipse.jdt.internal.compiler.util.SimpleSet;
0054:        import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
0055:        import org.eclipse.jdt.internal.core.hierarchy.HierarchyResolver;
0056:        import org.eclipse.jdt.internal.core.BinaryMember;
0057:        import org.eclipse.jdt.internal.core.BinaryType;
0058:        import org.eclipse.jdt.internal.core.ClassFile;
0059:        import org.eclipse.jdt.internal.core.CompilationUnit;
0060:        import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
0061:        import org.eclipse.jdt.internal.core.JavaElement;
0062:        import org.eclipse.jdt.internal.core.JavaModelManager;
0063:        import org.eclipse.jdt.internal.core.JavaProject;
0064:        import org.eclipse.jdt.internal.core.LocalVariable;
0065:        import org.eclipse.jdt.internal.core.NameLookup;
0066:        import org.eclipse.jdt.internal.core.Openable;
0067:        import org.eclipse.jdt.internal.core.PackageFragment;
0068:        import org.eclipse.jdt.internal.core.PackageFragmentRoot;
0069:        import org.eclipse.jdt.internal.core.SearchableEnvironment;
0070:        import org.eclipse.jdt.internal.core.SourceMapper;
0071:        import org.eclipse.jdt.internal.core.SourceMethod;
0072:        import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
0073:        import org.eclipse.jdt.internal.core.index.Index;
0074:        import org.eclipse.jdt.internal.core.search.*;
0075:        import org.eclipse.jdt.internal.core.util.HandleFactory;
0076:        import org.eclipse.jdt.internal.core.util.Util;
0077:
0078:        public class MatchLocator implements  ITypeRequestor {
0079:
0080:            public static final int MAX_AT_ONCE;
0081:            static {
0082:                long maxMemory = Runtime.getRuntime().maxMemory();
0083:                int ratio = (int) Math.round(((double) maxMemory)
0084:                        / (64 * 0x100000));
0085:                switch (ratio) {
0086:                case 0:
0087:                case 1:
0088:                    MAX_AT_ONCE = 100;
0089:                    break;
0090:                case 2:
0091:                    MAX_AT_ONCE = 200;
0092:                    break;
0093:                case 3:
0094:                    MAX_AT_ONCE = 300;
0095:                    break;
0096:                default:
0097:                    MAX_AT_ONCE = 400;
0098:                    break;
0099:                }
0100:            }
0101:
0102:            // permanent state
0103:            public SearchPattern pattern;
0104:            public PatternLocator patternLocator;
0105:            public int matchContainer;
0106:            public SearchRequestor requestor;
0107:            public IJavaSearchScope scope;
0108:            public IProgressMonitor progressMonitor;
0109:
0110:            public org.eclipse.jdt.core.ICompilationUnit[] workingCopies;
0111:            public HandleFactory handleFactory;
0112:
0113:            // cache of all super type names if scope is hierarchy scope
0114:            public char[][][] allSuperTypeNames;
0115:
0116:            // the following is valid for the current project
0117:            public MatchLocatorParser parser;
0118:            private Parser basicParser;
0119:            public INameEnvironment nameEnvironment;
0120:            public NameLookup nameLookup;
0121:            public LookupEnvironment lookupEnvironment;
0122:            public HierarchyResolver hierarchyResolver;
0123:
0124:            public CompilerOptions options;
0125:
0126:            // management of PossibleMatch to be processed
0127:            public int numberOfMatches; // (numberOfMatches - 1) is the last unit in matchesToProcess
0128:            public PossibleMatch[] matchesToProcess;
0129:            public PossibleMatch currentPossibleMatch;
0130:
0131:            /*
0132:             * Time spent in the IJavaSearchResultCollector
0133:             */
0134:            public long resultCollectorTime = 0;
0135:
0136:            // Progress information
0137:            int progressStep;
0138:            int progressWorked;
0139:
0140:            // Binding resolution and cache
0141:            CompilationUnitScope unitScope;
0142:            SimpleLookupTable bindings;
0143:
0144:            // Cache for method handles
0145:            HashSet methodHandles;
0146:
0147:            /**
0148:             * An ast visitor that visits local type declarations.
0149:             */
0150:            public class LocalDeclarationVisitor extends ASTVisitor {
0151:                IJavaElement enclosingElement;
0152:                Binding enclosingElementBinding;
0153:                MatchingNodeSet nodeSet;
0154:                HashtableOfIntValues occurrencesCounts = new HashtableOfIntValues(); // key = class name (char[]), value = occurrenceCount (int)
0155:
0156:                public LocalDeclarationVisitor(IJavaElement enclosingElement,
0157:                        Binding enclosingElementBinding, MatchingNodeSet nodeSet) {
0158:                    this .enclosingElement = enclosingElement;
0159:                    this .enclosingElementBinding = enclosingElementBinding;
0160:                    this .nodeSet = nodeSet;
0161:                }
0162:
0163:                public boolean visit(TypeDeclaration typeDeclaration,
0164:                        BlockScope unused) {
0165:                    try {
0166:                        char[] simpleName;
0167:                        if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
0168:                            simpleName = CharOperation.NO_CHAR;
0169:                        } else {
0170:                            simpleName = typeDeclaration.name;
0171:                        }
0172:                        int occurrenceCount = occurrencesCounts.get(simpleName);
0173:                        if (occurrenceCount == HashtableOfIntValues.NO_VALUE) {
0174:                            occurrenceCount = 1;
0175:                        } else {
0176:                            occurrenceCount = occurrenceCount + 1;
0177:                        }
0178:                        occurrencesCounts.put(simpleName, occurrenceCount);
0179:                        if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
0180:                            reportMatching(typeDeclaration,
0181:                                    this .enclosingElement, -1, nodeSet,
0182:                                    occurrenceCount);
0183:                        } else {
0184:                            Integer level = (Integer) nodeSet.matchingNodes
0185:                                    .removeKey(typeDeclaration);
0186:                            reportMatching(typeDeclaration,
0187:                                    this .enclosingElement,
0188:                                    level != null ? level.intValue() : -1,
0189:                                    nodeSet, occurrenceCount);
0190:                        }
0191:                        return false; // don't visit members as this was done during reportMatching(...)
0192:                    } catch (CoreException e) {
0193:                        throw new WrappedCoreException(e);
0194:                    }
0195:                }
0196:            }
0197:
0198:            public static class WorkingCopyDocument extends JavaSearchDocument {
0199:                public org.eclipse.jdt.core.ICompilationUnit workingCopy;
0200:
0201:                WorkingCopyDocument(
0202:                        org.eclipse.jdt.core.ICompilationUnit workingCopy,
0203:                        SearchParticipant participant) {
0204:                    super (workingCopy.getPath().toString(), participant);
0205:                    this .charContents = ((CompilationUnit) workingCopy)
0206:                            .getContents();
0207:                    this .workingCopy = workingCopy;
0208:                }
0209:
0210:                public String toString() {
0211:                    return "WorkingCopyDocument for " + getPath(); //$NON-NLS-1$
0212:                }
0213:            }
0214:
0215:            public static class WrappedCoreException extends RuntimeException {
0216:                private static final long serialVersionUID = 8354329870126121212L; // backward compatible
0217:                public CoreException coreException;
0218:
0219:                public WrappedCoreException(CoreException coreException) {
0220:                    this .coreException = coreException;
0221:                }
0222:            }
0223:
0224:            public static SearchDocument[] addWorkingCopies(
0225:                    InternalSearchPattern pattern,
0226:                    SearchDocument[] indexMatches,
0227:                    org.eclipse.jdt.core.ICompilationUnit[] copies,
0228:                    SearchParticipant participant) {
0229:                if (copies == null)
0230:                    return indexMatches;
0231:                // working copies take precedence over corresponding compilation units
0232:                HashMap workingCopyDocuments = workingCopiesThatCanSeeFocus(
0233:                        copies, pattern.focus, pattern.isPolymorphicSearch(),
0234:                        participant);
0235:                if (workingCopyDocuments.size() == 0)
0236:                    return indexMatches;
0237:                SearchDocument[] matches = null;
0238:                int length = indexMatches.length;
0239:                for (int i = 0; i < length; i++) {
0240:                    SearchDocument searchDocument = indexMatches[i];
0241:                    if (searchDocument.getParticipant() == participant) {
0242:                        SearchDocument workingCopyDocument = (SearchDocument) workingCopyDocuments
0243:                                .remove(searchDocument.getPath());
0244:                        if (workingCopyDocument != null) {
0245:                            if (matches == null) {
0246:                                System.arraycopy(indexMatches, 0,
0247:                                        matches = new SearchDocument[length],
0248:                                        0, length);
0249:                            }
0250:                            matches[i] = workingCopyDocument;
0251:                        }
0252:                    }
0253:                }
0254:                if (matches == null) { // no working copy
0255:                    matches = indexMatches;
0256:                }
0257:                int remainingWorkingCopiesSize = workingCopyDocuments.size();
0258:                if (remainingWorkingCopiesSize != 0) {
0259:                    System.arraycopy(matches, 0,
0260:                            matches = new SearchDocument[length
0261:                                    + remainingWorkingCopiesSize], 0, length);
0262:                    Iterator iterator = workingCopyDocuments.values()
0263:                            .iterator();
0264:                    int index = length;
0265:                    while (iterator.hasNext()) {
0266:                        matches[index++] = (SearchDocument) iterator.next();
0267:                    }
0268:                }
0269:                return matches;
0270:            }
0271:
0272:            public static void setFocus(InternalSearchPattern pattern,
0273:                    IJavaElement focus) {
0274:                pattern.focus = focus;
0275:            }
0276:
0277:            /*
0278:             * Returns the working copies that can see the given focus.
0279:             */
0280:            private static HashMap workingCopiesThatCanSeeFocus(
0281:                    org.eclipse.jdt.core.ICompilationUnit[] copies,
0282:                    IJavaElement focus, boolean isPolymorphicSearch,
0283:                    SearchParticipant participant) {
0284:                if (copies == null)
0285:                    return new HashMap();
0286:                if (focus != null) {
0287:                    while (!(focus instanceof  IJavaProject)
0288:                            && !(focus instanceof  JarPackageFragmentRoot)) {
0289:                        focus = focus.getParent();
0290:                    }
0291:                }
0292:                HashMap result = new HashMap();
0293:                for (int i = 0, length = copies.length; i < length; i++) {
0294:                    org.eclipse.jdt.core.ICompilationUnit workingCopy = copies[i];
0295:                    IPath projectOrJar = MatchLocator.getProjectOrJar(
0296:                            workingCopy).getPath();
0297:                    if (focus == null
0298:                            || IndexSelector.canSeeFocus(focus,
0299:                                    isPolymorphicSearch, projectOrJar)) {
0300:                        result.put(workingCopy.getPath().toString(),
0301:                                new WorkingCopyDocument(workingCopy,
0302:                                        participant));
0303:                    }
0304:                }
0305:                return result;
0306:            }
0307:
0308:            public static ClassFileReader classFileReader(IType type) {
0309:                IClassFile classFile = type.getClassFile();
0310:                JavaModelManager manager = JavaModelManager
0311:                        .getJavaModelManager();
0312:                if (classFile.isOpen())
0313:                    return (ClassFileReader) manager.getInfo(type);
0314:
0315:                PackageFragment pkg = (PackageFragment) type
0316:                        .getPackageFragment();
0317:                IPackageFragmentRoot root = (IPackageFragmentRoot) pkg
0318:                        .getParent();
0319:                try {
0320:                    if (!root.isArchive())
0321:                        return Util.newClassFileReader(type.getResource());
0322:
0323:                    ZipFile zipFile = null;
0324:                    try {
0325:                        IPath zipPath = root.getPath();
0326:                        if (JavaModelManager.ZIP_ACCESS_VERBOSE)
0327:                            System.out
0328:                                    .println("(" + Thread.currentThread() + ") [MatchLocator.classFileReader()] Creating ZipFile on " + zipPath); //$NON-NLS-1$	//$NON-NLS-2$
0329:                        zipFile = manager.getZipFile(zipPath);
0330:                        String classFileName = classFile.getElementName();
0331:                        String path = Util.concatWith(pkg.names, classFileName,
0332:                                '/');
0333:                        return ClassFileReader.read(zipFile, path);
0334:                    } finally {
0335:                        manager.closeZipFile(zipFile);
0336:                    }
0337:                } catch (ClassFormatException e) {
0338:                    // invalid class file: return null
0339:                } catch (CoreException e) {
0340:                    // cannot read class file: return null
0341:                } catch (IOException e) {
0342:                    // cannot read class file: return null
0343:                }
0344:                return null;
0345:            }
0346:
0347:            /**
0348:             * Query a given index for matching entries. Assumes the sender has opened the index and will close when finished.
0349:             */
0350:            public static void findIndexMatches(InternalSearchPattern pattern,
0351:                    Index index, IndexQueryRequestor requestor,
0352:                    SearchParticipant participant, IJavaSearchScope scope,
0353:                    IProgressMonitor monitor) throws IOException {
0354:                pattern.findIndexMatches(index, requestor, participant, scope,
0355:                        monitor);
0356:            }
0357:
0358:            public static IJavaElement getProjectOrJar(IJavaElement element) {
0359:                while (!(element instanceof  IJavaProject)
0360:                        && !(element instanceof  JarPackageFragmentRoot)) {
0361:                    element = element.getParent();
0362:                }
0363:                return element;
0364:            }
0365:
0366:            public static IJavaElement projectOrJarFocus(
0367:                    InternalSearchPattern pattern) {
0368:                return pattern == null || pattern.focus == null ? null
0369:                        : getProjectOrJar(pattern.focus);
0370:            }
0371:
0372:            public MatchLocator(SearchPattern pattern,
0373:                    SearchRequestor requestor, IJavaSearchScope scope,
0374:                    IProgressMonitor progressMonitor) {
0375:
0376:                this .pattern = pattern;
0377:                this .patternLocator = PatternLocator
0378:                        .patternLocator(this .pattern);
0379:                this .matchContainer = this .patternLocator == null ? 0
0380:                        : this .patternLocator.matchContainer();
0381:                this .requestor = requestor;
0382:                this .scope = scope;
0383:                this .progressMonitor = progressMonitor;
0384:            }
0385:
0386:            /**
0387:             * Add an additional binary type
0388:             */
0389:            public void accept(IBinaryType binaryType,
0390:                    PackageBinding packageBinding,
0391:                    AccessRestriction accessRestriction) {
0392:                this .lookupEnvironment.createBinaryTypeFrom(binaryType,
0393:                        packageBinding, accessRestriction);
0394:            }
0395:
0396:            /**
0397:             * Add an additional compilation unit into the loop
0398:             *  ->  build compilation unit declarations, their bindings and record their results.
0399:             */
0400:            public void accept(ICompilationUnit sourceUnit,
0401:                    AccessRestriction accessRestriction) {
0402:                // Switch the current policy and compilation result for this unit to the requested one.
0403:                CompilationResult unitResult = new CompilationResult(
0404:                        sourceUnit, 1, 1, this .options.maxProblemsPerUnit);
0405:                try {
0406:                    CompilationUnitDeclaration parsedUnit = basicParser()
0407:                            .dietParse(sourceUnit, unitResult);
0408:                    this .lookupEnvironment.buildTypeBindings(parsedUnit,
0409:                            accessRestriction);
0410:                    this .lookupEnvironment.completeTypeBindings(parsedUnit,
0411:                            true);
0412:                } catch (AbortCompilationUnit e) {
0413:                    // at this point, currentCompilationUnitResult may not be sourceUnit, but some other
0414:                    // one requested further along to resolve sourceUnit.
0415:                    if (unitResult.compilationUnit == sourceUnit) { // only report once
0416:                        //requestor.acceptResult(unitResult.tagAsAccepted());
0417:                    } else {
0418:                        throw e; // want to abort enclosing request to compile
0419:                    }
0420:                }
0421:                // Display unit error in debug mode
0422:                if (BasicSearchEngine.VERBOSE) {
0423:                    if (unitResult.problemCount > 0) {
0424:                        System.out.println(unitResult);
0425:                    }
0426:                }
0427:            }
0428:
0429:            /**
0430:             * Add additional source types
0431:             */
0432:            public void accept(ISourceType[] sourceTypes,
0433:                    PackageBinding packageBinding,
0434:                    AccessRestriction accessRestriction) {
0435:                // case of SearchableEnvironment of an IJavaProject is used
0436:                ISourceType sourceType = sourceTypes[0];
0437:                while (sourceType.getEnclosingType() != null)
0438:                    sourceType = sourceType.getEnclosingType();
0439:                if (sourceType instanceof  SourceTypeElementInfo) {
0440:                    // get source
0441:                    SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) sourceType;
0442:                    IType type = elementInfo.getHandle();
0443:                    ICompilationUnit sourceUnit = (ICompilationUnit) type
0444:                            .getCompilationUnit();
0445:                    accept(sourceUnit, accessRestriction);
0446:                } else {
0447:                    CompilationResult result = new CompilationResult(sourceType
0448:                            .getFileName(), 1, 1, 0);
0449:                    CompilationUnitDeclaration unit = SourceTypeConverter
0450:                            .buildCompilationUnit(
0451:                                    sourceTypes,
0452:                                    SourceTypeConverter.FIELD_AND_METHOD // need field and methods
0453:                                            | SourceTypeConverter.MEMBER_TYPE, // need member types
0454:                                    // no need for field initialization
0455:                                    this .lookupEnvironment.problemReporter,
0456:                                    result);
0457:                    this .lookupEnvironment.buildTypeBindings(unit,
0458:                            accessRestriction);
0459:                    this .lookupEnvironment.completeTypeBindings(unit, true);
0460:                }
0461:            }
0462:
0463:            protected Parser basicParser() {
0464:                if (this .basicParser == null) {
0465:                    ProblemReporter problemReporter = new ProblemReporter(
0466:                            DefaultErrorHandlingPolicies
0467:                                    .proceedWithAllProblems(), this .options,
0468:                            new DefaultProblemFactory());
0469:                    this .basicParser = new Parser(problemReporter, false);
0470:                    this .basicParser.reportOnlyOneSyntaxError = true;
0471:                }
0472:                return this .basicParser;
0473:            }
0474:
0475:            /*
0476:             * Caches the given binary type in the lookup environment and returns it.
0477:             * Returns the existing one if already cached.
0478:             * Returns null if source type binding was cached.
0479:             */
0480:            protected BinaryTypeBinding cacheBinaryType(IType type,
0481:                    IBinaryType binaryType) throws JavaModelException {
0482:                IType enclosingType = type.getDeclaringType();
0483:                if (enclosingType != null)
0484:                    cacheBinaryType(enclosingType, null); // cache enclosing types first, so that binary type can be found in lookup enviroment
0485:                if (binaryType == null) {
0486:                    ClassFile classFile = (ClassFile) type.getClassFile();
0487:                    try {
0488:                        binaryType = getBinaryInfo(classFile, classFile
0489:                                .getResource());
0490:                    } catch (CoreException e) {
0491:                        if (e instanceof  JavaModelException) {
0492:                            throw (JavaModelException) e;
0493:                        } else {
0494:                            throw new JavaModelException(e);
0495:                        }
0496:                    }
0497:                }
0498:                BinaryTypeBinding binding = this .lookupEnvironment
0499:                        .cacheBinaryType(binaryType, null /*no access restriction*/);
0500:                if (binding == null) { // it was already cached as a result of a previous query
0501:                    char[][] compoundName = CharOperation.splitOn('.', type
0502:                            .getFullyQualifiedName().toCharArray());
0503:                    ReferenceBinding referenceBinding = this .lookupEnvironment
0504:                            .getCachedType(compoundName);
0505:                    if (referenceBinding != null
0506:                            && (referenceBinding instanceof  BinaryTypeBinding))
0507:                        binding = (BinaryTypeBinding) referenceBinding; // if the binding could be found and if it comes from a binary type
0508:                }
0509:                return binding;
0510:            }
0511:
0512:            /*
0513:             * Computes the super type names of the focus type if any.
0514:             */
0515:            protected char[][][] computeSuperTypeNames(IType focusType) {
0516:                String fullyQualifiedName = focusType.getFullyQualifiedName();
0517:                int lastDot = fullyQualifiedName.lastIndexOf('.');
0518:                char[] qualification = lastDot == -1 ? CharOperation.NO_CHAR
0519:                        : fullyQualifiedName.substring(0, lastDot)
0520:                                .toCharArray();
0521:                char[] simpleName = focusType.getElementName().toCharArray();
0522:
0523:                SuperTypeNamesCollector super TypeNamesCollector = new SuperTypeNamesCollector(
0524:                        this .pattern, simpleName, qualification,
0525:                        new MatchLocator(this .pattern, this .requestor,
0526:                                this .scope, this .progressMonitor), // clone MatchLocator so that it has no side effect
0527:                        focusType, this .progressMonitor);
0528:                try {
0529:                    this .allSuperTypeNames = super TypeNamesCollector.collect();
0530:                } catch (JavaModelException e) {
0531:                    // problem collecting super type names: leave it null
0532:                }
0533:                return this .allSuperTypeNames;
0534:            }
0535:
0536:            /**
0537:             * Creates an IMethod from the given method declaration and type. 
0538:             */
0539:            protected IJavaElement createHandle(
0540:                    AbstractMethodDeclaration method, IJavaElement parent) {
0541:                if (!(parent instanceof  IType))
0542:                    return parent;
0543:
0544:                IType type = (IType) parent;
0545:                Argument[] arguments = method.arguments;
0546:                int argCount = arguments == null ? 0 : arguments.length;
0547:                if (type.isBinary()) {
0548:                    // don't cache the methods of the binary type
0549:                    // fall thru if its a constructor with a synthetic argument... find it the slower way
0550:                    ClassFileReader reader = classFileReader(type);
0551:                    if (reader != null) {
0552:                        IBinaryMethod[] methods = reader.getMethods();
0553:                        if (methods != null) {
0554:                            // build arguments names
0555:                            boolean firstIsSynthetic = false;
0556:                            if (reader.isMember() && method.isConstructor()
0557:                                    && !Flags.isStatic(reader.getModifiers())) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=48261
0558:                                firstIsSynthetic = true;
0559:                                argCount++;
0560:                            }
0561:                            char[][] argumentTypeNames = new char[argCount][];
0562:                            for (int i = 0; i < argCount; i++) {
0563:                                char[] typeName = null;
0564:                                if (i == 0 && firstIsSynthetic) {
0565:                                    typeName = type.getDeclaringType()
0566:                                            .getFullyQualifiedName()
0567:                                            .toCharArray();
0568:                                } else if (arguments != null) {
0569:                                    TypeReference typeRef = arguments[firstIsSynthetic ? i - 1
0570:                                            : i].type;
0571:                                    typeName = CharOperation.concatWith(typeRef
0572:                                            .getTypeName(), '.');
0573:                                    for (int k = 0, dim = typeRef.dimensions(); k < dim; k++)
0574:                                        typeName = CharOperation.concat(
0575:                                                typeName,
0576:                                                new char[] { '[', ']' });
0577:                                }
0578:                                if (typeName == null) {
0579:                                    // invalid type name
0580:                                    return null;
0581:                                }
0582:                                argumentTypeNames[i] = typeName;
0583:                            }
0584:
0585:                            // return binary method
0586:                            return createBinaryMethodHandle(type,
0587:                                    method.selector, argumentTypeNames);
0588:                        }
0589:                    }
0590:                    return null;
0591:                }
0592:
0593:                String[] parameterTypeSignatures = new String[argCount];
0594:                if (arguments != null) {
0595:                    for (int i = 0; i < argCount; i++) {
0596:                        TypeReference typeRef = arguments[i].type;
0597:                        char[] typeName = CharOperation.concatWith(typeRef
0598:                                .getParameterizedTypeName(), '.');
0599:                        parameterTypeSignatures[i] = Signature
0600:                                .createTypeSignature(typeName, false);
0601:                    }
0602:                }
0603:
0604:                return createMethodHandle(type, new String(method.selector),
0605:                        parameterTypeSignatures);
0606:            }
0607:
0608:            /*
0609:             * Create binary method handle
0610:             */
0611:            IMethod createBinaryMethodHandle(IType type, char[] methodSelector,
0612:                    char[][] argumentTypeNames) {
0613:                ClassFileReader reader = MatchLocator.classFileReader(type);
0614:                if (reader != null) {
0615:                    IBinaryMethod[] methods = reader.getMethods();
0616:                    if (methods != null) {
0617:                        int argCount = argumentTypeNames == null ? 0
0618:                                : argumentTypeNames.length;
0619:                        nextMethod: for (int i = 0, methodsLength = methods.length; i < methodsLength; i++) {
0620:                            IBinaryMethod binaryMethod = methods[i];
0621:                            char[] selector = binaryMethod.isConstructor() ? type
0622:                                    .getElementName().toCharArray()
0623:                                    : binaryMethod.getSelector();
0624:                            if (CharOperation.equals(selector, methodSelector)) {
0625:                                char[] signature = binaryMethod
0626:                                        .getGenericSignature();
0627:                                if (signature == null)
0628:                                    signature = binaryMethod
0629:                                            .getMethodDescriptor();
0630:                                char[][] parameterTypes = Signature
0631:                                        .getParameterTypes(signature);
0632:                                if (argCount != parameterTypes.length)
0633:                                    continue nextMethod;
0634:                                if (argumentTypeNames != null) {
0635:                                    for (int j = 0; j < argCount; j++) {
0636:                                        char[] parameterTypeName = ClassFileMatchLocator
0637:                                                .convertClassFileFormat(parameterTypes[j]);
0638:                                        if (!CharOperation
0639:                                                .endsWith(
0640:                                                        Signature
0641:                                                                .toCharArray(Signature
0642:                                                                        .getTypeErasure(parameterTypeName)),
0643:                                                        CharOperation
0644:                                                                .replaceOnCopy(
0645:                                                                        argumentTypeNames[j],
0646:                                                                        '$',
0647:                                                                        '.')))
0648:                                            continue nextMethod;
0649:                                        parameterTypes[j] = parameterTypeName;
0650:                                    }
0651:                                }
0652:                                return (IMethod) createMethodHandle(type,
0653:                                        new String(selector), CharOperation
0654:                                                .toStrings(parameterTypes));
0655:                            }
0656:                        }
0657:                    }
0658:                }
0659:                return null;
0660:            }
0661:
0662:            /*
0663:             * Create method handle.
0664:             * Store occurences for create handle to retrieve possible duplicate ones.
0665:             */
0666:            private IJavaElement createMethodHandle(IType type,
0667:                    String methodName, String[] parameterTypeSignatures) {
0668:                IMethod methodHandle = type.getMethod(methodName,
0669:                        parameterTypeSignatures);
0670:                if (methodHandle instanceof  SourceMethod) {
0671:                    while (this .methodHandles.contains(methodHandle)) {
0672:                        ((SourceMethod) methodHandle).occurrenceCount++;
0673:                    }
0674:                }
0675:                this .methodHandles.add(methodHandle);
0676:                return methodHandle;
0677:            }
0678:
0679:            /**
0680:             * Creates an IField from the given field declaration and type. 
0681:             */
0682:            protected IJavaElement createHandle(
0683:                    FieldDeclaration fieldDeclaration,
0684:                    TypeDeclaration typeDeclaration, IJavaElement parent) {
0685:                if (!(parent instanceof  IType))
0686:                    return parent;
0687:                IType type = (IType) parent;
0688:
0689:                switch (fieldDeclaration.getKind()) {
0690:                case AbstractVariableDeclaration.FIELD:
0691:                case AbstractVariableDeclaration.ENUM_CONSTANT:
0692:                    return ((IType) parent).getField(new String(
0693:                            fieldDeclaration.name));
0694:                }
0695:                if (type.isBinary()) {
0696:                    // do not return initializer for binary types
0697:                    // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=98378
0698:                    return type;
0699:                }
0700:                // find occurence count of the given initializer in its type declaration
0701:                int occurrenceCount = 0;
0702:                FieldDeclaration[] fields = typeDeclaration.fields;
0703:                for (int i = 0, length = fields.length; i < length; i++) {
0704:                    if (fields[i].getKind() == AbstractVariableDeclaration.INITIALIZER) {
0705:                        occurrenceCount++;
0706:                        if (fields[i].equals(fieldDeclaration))
0707:                            break;
0708:                    }
0709:                }
0710:                return ((IType) parent).getInitializer(occurrenceCount);
0711:            }
0712:
0713:            /**
0714:             * Create an handle for a local variable declartion (may be a local variable or type parameter).
0715:             */
0716:            protected IJavaElement createHandle(
0717:                    AbstractVariableDeclaration variableDeclaration,
0718:                    IJavaElement parent) {
0719:                switch (variableDeclaration.getKind()) {
0720:                case AbstractVariableDeclaration.LOCAL_VARIABLE:
0721:                    return new LocalVariable((JavaElement) parent, new String(
0722:                            variableDeclaration.name),
0723:                            variableDeclaration.declarationSourceStart,
0724:                            variableDeclaration.declarationSourceEnd,
0725:                            variableDeclaration.sourceStart,
0726:                            variableDeclaration.sourceEnd, new String(
0727:                                    variableDeclaration.type.resolvedType
0728:                                            .signature()));
0729:                case AbstractVariableDeclaration.PARAMETER:
0730:                    return new LocalVariable((JavaElement) parent, new String(
0731:                            variableDeclaration.name),
0732:                            variableDeclaration.declarationSourceStart,
0733:                            variableDeclaration.declarationSourceEnd,
0734:                            variableDeclaration.sourceStart,
0735:                            variableDeclaration.sourceEnd, new String(
0736:                                    variableDeclaration.type.resolvedType
0737:                                            .signature()));
0738:                case AbstractVariableDeclaration.TYPE_PARAMETER:
0739:                    return new org.eclipse.jdt.internal.core.TypeParameter(
0740:                            (JavaElement) parent, new String(
0741:                                    variableDeclaration.name));
0742:                }
0743:                return null;
0744:            }
0745:
0746:            /*
0747:             * Creates hierarchy resolver if needed. 
0748:             * Returns whether focus is visible.
0749:             */
0750:            protected boolean createHierarchyResolver(IType focusType,
0751:                    PossibleMatch[] possibleMatches) {
0752:                // cache focus type if not a possible match
0753:                char[][] compoundName = CharOperation.splitOn('.', focusType
0754:                        .getFullyQualifiedName().toCharArray());
0755:                boolean isPossibleMatch = false;
0756:                for (int i = 0, length = possibleMatches.length; i < length; i++) {
0757:                    if (CharOperation.equals(possibleMatches[i].compoundName,
0758:                            compoundName)) {
0759:                        isPossibleMatch = true;
0760:                        break;
0761:                    }
0762:                }
0763:                if (!isPossibleMatch) {
0764:                    if (focusType.isBinary()) {
0765:                        try {
0766:                            cacheBinaryType(focusType, null);
0767:                        } catch (JavaModelException e) {
0768:                            return false;
0769:                        }
0770:                    } else {
0771:                        // cache all types in the focus' compilation unit (even secondary types)
0772:                        accept((ICompilationUnit) focusType
0773:                                .getCompilationUnit(), null /*TODO no access restriction*/);
0774:                    }
0775:                }
0776:
0777:                // resolve focus type
0778:                this .hierarchyResolver = new HierarchyResolver(
0779:                        this .lookupEnvironment, null/*hierarchy is not going to be computed*/);
0780:                ReferenceBinding binding = this .hierarchyResolver
0781:                        .setFocusType(compoundName);
0782:                return binding != null
0783:                        && binding.isValidBinding()
0784:                        && (binding.tagBits & TagBits.HierarchyHasProblems) == 0;
0785:            }
0786:
0787:            /**
0788:             * Creates an IImportDeclaration from the given import statement
0789:             */
0790:            protected IJavaElement createImportHandle(ImportReference importRef) {
0791:                char[] importName = CharOperation.concatWith(importRef
0792:                        .getImportName(), '.');
0793:                if ((importRef.bits & ASTNode.OnDemand) != 0)
0794:                    importName = CharOperation.concat(importName,
0795:                            ".*".toCharArray()); //$NON-NLS-1$
0796:                Openable openable = this .currentPossibleMatch.openable;
0797:                if (openable instanceof  CompilationUnit)
0798:                    return ((CompilationUnit) openable).getImport(new String(
0799:                            importName));
0800:
0801:                // binary types do not contain import statements so just answer the top-level type as the element
0802:                IType binaryType = ((ClassFile) openable).getType();
0803:                String typeName = binaryType.getElementName();
0804:                int lastDollar = typeName.lastIndexOf('$');
0805:                if (lastDollar == -1)
0806:                    return binaryType;
0807:                return createTypeHandle(typeName.substring(0, lastDollar));
0808:            }
0809:
0810:            /**
0811:             * Creates an IImportDeclaration from the given import statement
0812:             */
0813:            protected IJavaElement createPackageDeclarationHandle(
0814:                    CompilationUnitDeclaration unit) {
0815:                if (unit.isPackageInfo()) {
0816:                    char[] packName = CharOperation.concatWith(
0817:                            unit.currentPackage.getImportName(), '.');
0818:                    Openable openable = this .currentPossibleMatch.openable;
0819:                    if (openable instanceof  CompilationUnit) {
0820:                        return ((CompilationUnit) openable)
0821:                                .getPackageDeclaration(new String(packName));
0822:                    }
0823:                }
0824:                return createTypeHandle(new String(unit.getMainTypeName()));
0825:            }
0826:
0827:            /**
0828:             * Creates an IType from the given simple top level type name. 
0829:             */
0830:            protected IType createTypeHandle(String simpleTypeName) {
0831:                Openable openable = this .currentPossibleMatch.openable;
0832:                if (openable instanceof  CompilationUnit)
0833:                    return ((CompilationUnit) openable).getType(simpleTypeName);
0834:
0835:                IType binaryType = ((ClassFile) openable).getType();
0836:                String binaryTypeQualifiedName = binaryType
0837:                        .getTypeQualifiedName();
0838:                if (simpleTypeName.equals(binaryTypeQualifiedName))
0839:                    return binaryType; // answer only top-level types, sometimes the classFile is for a member/local type
0840:
0841:                // type name may be null for anonymous (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=164791)
0842:                String classFileName = simpleTypeName.length() == 0 ? binaryTypeQualifiedName
0843:                        : simpleTypeName;
0844:                IClassFile classFile = binaryType.getPackageFragment()
0845:                        .getClassFile(
0846:                                classFileName
0847:                                        + SuffixConstants.SUFFIX_STRING_class);
0848:                return classFile.getType();
0849:            }
0850:
0851:            protected boolean encloses(IJavaElement element) {
0852:                return element != null && this .scope.encloses(element);
0853:            }
0854:
0855:            /* (non-Javadoc)
0856:             * Return info about last type argument of a parameterized type reference.
0857:             * These info are made of concatenation of 2 int values which are respectively
0858:             *  depth and end position of the last type argument.
0859:             * For example, this method will return 0x300000020 for type ref List<List<List<String>>>
0860:             * if end position of type reference "String" equals 32.
0861:             */
0862:            private long findLastTypeArgumentInfo(TypeReference typeRef) {
0863:                // Get last list of type arguments for parameterized qualified type reference
0864:                TypeReference lastTypeArgument = typeRef;
0865:                int depth = 0;
0866:                while (true) {
0867:                    TypeReference[] lastTypeArguments = null;
0868:                    if (lastTypeArgument instanceof  ParameterizedQualifiedTypeReference) {
0869:                        ParameterizedQualifiedTypeReference pqtRef = (ParameterizedQualifiedTypeReference) lastTypeArgument;
0870:                        for (int i = pqtRef.typeArguments.length - 1; i >= 0
0871:                                && lastTypeArguments == null; i--) {
0872:                            lastTypeArguments = pqtRef.typeArguments[i];
0873:                        }
0874:                    }
0875:                    // Get last type argument for single type reference of last list of argument of parameterized qualified type reference
0876:                    TypeReference last = null;
0877:                    if (lastTypeArgument instanceof  ParameterizedSingleTypeReference
0878:                            || lastTypeArguments != null) {
0879:                        if (lastTypeArguments == null) {
0880:                            lastTypeArguments = ((ParameterizedSingleTypeReference) lastTypeArgument).typeArguments;
0881:                        }
0882:                        if (lastTypeArguments != null) {
0883:                            for (int i = lastTypeArguments.length - 1; i >= 0
0884:                                    && last == null; i++) {
0885:                                last = lastTypeArguments[i];
0886:                            }
0887:                        }
0888:                    }
0889:                    if (last == null)
0890:                        break;
0891:                    depth++;
0892:                    lastTypeArgument = last;
0893:                }
0894:                // Current type reference is not parameterized. So, it is the last type argument
0895:                return (((long) depth) << 32) + lastTypeArgument.sourceEnd;
0896:            }
0897:
0898:            protected IBinaryType getBinaryInfo(ClassFile classFile,
0899:                    IResource resource) throws CoreException {
0900:                BinaryType binaryType = (BinaryType) classFile.getType();
0901:                if (classFile.isOpen())
0902:                    return (IBinaryType) binaryType.getElementInfo(); // reuse the info from the java model cache
0903:
0904:                // create a temporary info
0905:                IBinaryType info;
0906:                try {
0907:                    PackageFragment pkg = (PackageFragment) classFile
0908:                            .getParent();
0909:                    PackageFragmentRoot root = (PackageFragmentRoot) pkg
0910:                            .getParent();
0911:                    if (root.isArchive()) {
0912:                        // class file in a jar
0913:                        String classFileName = classFile.getElementName();
0914:                        String classFilePath = Util.concatWith(pkg.names,
0915:                                classFileName, '/');
0916:                        ZipFile zipFile = null;
0917:                        try {
0918:                            zipFile = ((JarPackageFragmentRoot) root).getJar();
0919:                            info = ClassFileReader.read(zipFile, classFilePath);
0920:                        } finally {
0921:                            JavaModelManager.getJavaModelManager()
0922:                                    .closeZipFile(zipFile);
0923:                        }
0924:                    } else {
0925:                        // class file in a directory
0926:                        info = Util.newClassFileReader(resource);
0927:                    }
0928:                    if (info == null)
0929:                        throw binaryType.newNotPresentException();
0930:                    return info;
0931:                } catch (ClassFormatException e) {
0932:                    //e.printStackTrace();
0933:                    return null;
0934:                } catch (java.io.IOException e) {
0935:                    throw new JavaModelException(e,
0936:                            IJavaModelStatusConstants.IO_EXCEPTION);
0937:                }
0938:            }
0939:
0940:            protected IType getFocusType() {
0941:                return this .scope instanceof  HierarchyScope ? ((HierarchyScope) this .scope).focusType
0942:                        : null;
0943:            }
0944:
0945:            protected void getMethodBodies(CompilationUnitDeclaration unit,
0946:                    MatchingNodeSet nodeSet) {
0947:                if (unit.ignoreMethodBodies) {
0948:                    unit.ignoreFurtherInvestigation = true;
0949:                    return; // if initial diet parse did not work, no need to dig into method bodies.
0950:                }
0951:
0952:                // save existing values to restore them at the end of the parsing process
0953:                // see bug 47079 for more details
0954:                int[] oldLineEnds = this .parser.scanner.lineEnds;
0955:                int oldLinePtr = this .parser.scanner.linePtr;
0956:
0957:                try {
0958:                    CompilationResult compilationResult = unit.compilationResult;
0959:                    this .parser.scanner.setSource(compilationResult);
0960:
0961:                    if (this .parser.javadocParser.checkDocComment) {
0962:                        char[] contents = compilationResult.compilationUnit
0963:                                .getContents();
0964:                        this .parser.javadocParser.scanner.setSource(contents);
0965:                    }
0966:                    this .parser.nodeSet = nodeSet;
0967:                    this .parser.parseBodies(unit);
0968:                } finally {
0969:                    this .parser.nodeSet = null;
0970:                    // this is done to prevent any side effects on the compilation unit result
0971:                    // line separator positions array.
0972:                    this .parser.scanner.lineEnds = oldLineEnds;
0973:                    this .parser.scanner.linePtr = oldLinePtr;
0974:                }
0975:            }
0976:
0977:            protected TypeBinding getType(Object typeKey, char[] typeName) {
0978:                if (this .unitScope == null || typeName == null
0979:                        || typeName.length == 0)
0980:                    return null;
0981:                // Try to get binding from cache
0982:                Binding binding = (Binding) this .bindings.get(typeKey);
0983:                if (binding != null) {
0984:                    if (binding instanceof  TypeBinding
0985:                            && binding.isValidBinding())
0986:                        return (TypeBinding) binding;
0987:                    return null;
0988:                }
0989:                // Get binding from unit scope
0990:                char[][] compoundName = CharOperation.splitOn('.', typeName);
0991:                TypeBinding typeBinding = this .unitScope.getType(compoundName,
0992:                        compoundName.length);
0993:                this .bindings.put(typeKey, typeBinding);
0994:                return typeBinding.isValidBinding() ? typeBinding : null;
0995:            }
0996:
0997:            public MethodBinding getMethodBinding(MethodPattern methodPattern) {
0998:                if (this .unitScope == null)
0999:                    return null;
1000:                // Try to get binding from cache
1001:                Binding binding = (Binding) this .bindings.get(methodPattern);
1002:                if (binding != null) {
1003:                    if (binding instanceof  MethodBinding
1004:                            && binding.isValidBinding())
1005:                        return (MethodBinding) binding;
1006:                    return null;
1007:                }
1008:                //	Get binding from unit scope
1009:                char[] typeName = PatternLocator.qualifiedPattern(
1010:                        methodPattern.declaringSimpleName,
1011:                        methodPattern.declaringQualification);
1012:                if (typeName == null) {
1013:                    if (methodPattern.declaringType == null)
1014:                        return null;
1015:                    typeName = methodPattern.declaringType
1016:                            .getFullyQualifiedName().toCharArray();
1017:                }
1018:                TypeBinding declaringTypeBinding = getType(typeName, typeName);
1019:                if (declaringTypeBinding != null) {
1020:                    if (declaringTypeBinding.isArrayType()) {
1021:                        declaringTypeBinding = declaringTypeBinding
1022:                                .leafComponentType();
1023:                    }
1024:                    if (!declaringTypeBinding.isBaseType()) {
1025:                        char[][] parameterTypes = methodPattern.parameterSimpleNames;
1026:                        if (parameterTypes == null)
1027:                            return null;
1028:                        int paramTypeslength = parameterTypes.length;
1029:                        ReferenceBinding referenceBinding = (ReferenceBinding) declaringTypeBinding;
1030:                        MethodBinding[] methods = referenceBinding
1031:                                .getMethods(methodPattern.selector);
1032:                        int methodsLength = methods.length;
1033:                        TypeVariableBinding[] refTypeVariables = referenceBinding
1034:                                .typeVariables();
1035:                        int typeVarLength = refTypeVariables == null ? 0
1036:                                : refTypeVariables.length;
1037:                        for (int i = 0; i < methodsLength; i++) {
1038:                            TypeBinding[] methodParameters = methods[i].parameters;
1039:                            int paramLength = methodParameters == null ? 0
1040:                                    : methodParameters.length;
1041:                            TypeVariableBinding[] methodTypeVariables = methods[i].typeVariables;
1042:                            int methTypeVarLength = methodTypeVariables == null ? 0
1043:                                    : methodTypeVariables.length;
1044:                            boolean found = false;
1045:                            if (methodParameters != null
1046:                                    && paramLength == paramTypeslength) {
1047:                                for (int p = 0; p < paramLength; p++) {
1048:                                    if (CharOperation.equals(
1049:                                            methodParameters[p].sourceName(),
1050:                                            parameterTypes[p])) {
1051:                                        // param erasure match
1052:                                        found = true;
1053:                                    } else {
1054:                                        // type variable
1055:                                        found = false;
1056:                                        if (refTypeVariables != null) {
1057:                                            for (int v = 0; v < typeVarLength; v++) {
1058:                                                if (!CharOperation
1059:                                                        .equals(
1060:                                                                refTypeVariables[v].sourceName,
1061:                                                                parameterTypes[p])) {
1062:                                                    found = false;
1063:                                                    break;
1064:                                                }
1065:                                                found = true;
1066:                                            }
1067:                                        }
1068:                                        if (!found
1069:                                                && methodTypeVariables != null) {
1070:                                            for (int v = 0; v < methTypeVarLength; v++) {
1071:                                                if (!CharOperation
1072:                                                        .equals(
1073:                                                                methodTypeVariables[v].sourceName,
1074:                                                                parameterTypes[p])) {
1075:                                                    found = false;
1076:                                                    break;
1077:                                                }
1078:                                                found = true;
1079:                                            }
1080:                                        }
1081:                                        if (!found)
1082:                                            break;
1083:                                    }
1084:                                }
1085:                            }
1086:                            if (found) {
1087:                                this .bindings.put(methodPattern, methods[i]);
1088:                                return methods[i];
1089:                            }
1090:                        }
1091:                    }
1092:                }
1093:                this .bindings.put(methodPattern, new ProblemMethodBinding(
1094:                        methodPattern.selector, null, ProblemReasons.NotFound));
1095:                return null;
1096:            }
1097:
1098:            protected boolean hasAlreadyDefinedType(
1099:                    CompilationUnitDeclaration parsedUnit) {
1100:                CompilationResult result = parsedUnit.compilationResult;
1101:                if (result == null)
1102:                    return false;
1103:                for (int i = 0; i < result.problemCount; i++)
1104:                    if (result.problems[i].getID() == IProblem.DuplicateTypes)
1105:                        return true;
1106:                return false;
1107:            }
1108:
1109:            /**
1110:             * Create a new parser for the given project, as well as a lookup environment.
1111:             */
1112:            public void initialize(JavaProject project, int possibleMatchSize)
1113:                    throws JavaModelException {
1114:                // clean up name environment only if there are several possible match as it is reused
1115:                // when only one possible match (bug 58581)
1116:                if (this .nameEnvironment != null && possibleMatchSize != 1)
1117:                    this .nameEnvironment.cleanup();
1118:
1119:                SearchableEnvironment searchableEnvironment = project
1120:                        .newSearchableNameEnvironment(this .workingCopies);
1121:
1122:                // if only one possible match, a file name environment costs too much,
1123:                // so use the existing searchable  environment which will populate the java model
1124:                // only for this possible match and its required types.
1125:                this .nameEnvironment = possibleMatchSize == 1 ? (INameEnvironment) searchableEnvironment
1126:                        : (INameEnvironment) new JavaSearchNameEnvironment(
1127:                                project, this .workingCopies);
1128:
1129:                // create lookup environment
1130:                Map map = project.getOptions(true);
1131:                map.put(CompilerOptions.OPTION_TaskTags, ""); //$NON-NLS-1$
1132:                this .options = new CompilerOptions(map);
1133:                ProblemReporter problemReporter = new ProblemReporter(
1134:                        DefaultErrorHandlingPolicies.proceedWithAllProblems(),
1135:                        this .options, new DefaultProblemFactory());
1136:                this .lookupEnvironment = new LookupEnvironment(this ,
1137:                        this .options, problemReporter, this .nameEnvironment);
1138:
1139:                this .parser = MatchLocatorParser.createParser(problemReporter,
1140:                        this );
1141:
1142:                // basic parser needs also to be reset as project options may have changed
1143:                // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=163072
1144:                this .basicParser = null;
1145:
1146:                // remember project's name lookup
1147:                this .nameLookup = searchableEnvironment.nameLookup;
1148:
1149:                // initialize queue of units
1150:                this .numberOfMatches = 0;
1151:                this .matchesToProcess = new PossibleMatch[possibleMatchSize];
1152:            }
1153:
1154:            protected void locateMatches(JavaProject javaProject,
1155:                    PossibleMatch[] possibleMatches, int start, int length)
1156:                    throws CoreException {
1157:                initialize(javaProject, length);
1158:
1159:                // create and resolve binding (equivalent to beginCompilation() in Compiler)
1160:                boolean mustResolvePattern = ((InternalSearchPattern) this .pattern).mustResolve;
1161:                boolean mustResolve = mustResolvePattern;
1162:                this .patternLocator.mayBeGeneric = this .options.sourceLevel >= ClassFileConstants.JDK1_5;
1163:                boolean bindingsWereCreated = mustResolve;
1164:                try {
1165:                    for (int i = start, maxUnits = start + length; i < maxUnits; i++) {
1166:                        PossibleMatch possibleMatch = possibleMatches[i];
1167:                        try {
1168:                            if (!parseAndBuildBindings(possibleMatch,
1169:                                    mustResolvePattern))
1170:                                continue;
1171:                            // Currently we only need to resolve over pattern flag if there's potential parameterized types
1172:                            if (this .patternLocator.mayBeGeneric) {
1173:                                // If pattern does not resolve then rely on possible match node set resolution
1174:                                // which may have been modified while locator was adding possible matches to it
1175:                                if (!mustResolvePattern && !mustResolve) {
1176:                                    mustResolve = possibleMatch.nodeSet.mustResolve;
1177:                                    bindingsWereCreated = mustResolve;
1178:                                }
1179:                            } else {
1180:                                // Reset matching node resolution with pattern one if there's no potential parameterized type
1181:                                // to minimize side effect on previous search behavior
1182:                                possibleMatch.nodeSet.mustResolve = mustResolvePattern;
1183:                            }
1184:                            // possible match node resolution has been merged with pattern one, so rely on it to know
1185:                            // whether we need to process compilation unit now or later
1186:                            if (!possibleMatch.nodeSet.mustResolve) {
1187:                                if (this .progressMonitor != null) {
1188:                                    this .progressWorked++;
1189:                                    if ((this .progressWorked % this .progressStep) == 0)
1190:                                        this .progressMonitor
1191:                                                .worked(this .progressStep);
1192:                                }
1193:                                process(possibleMatch, bindingsWereCreated);
1194:                                if (this .numberOfMatches > 0
1195:                                        && this .matchesToProcess[this .numberOfMatches - 1] == possibleMatch) {
1196:                                    // forget last possible match as it was processed
1197:                                    this .numberOfMatches--;
1198:                                }
1199:                            }
1200:                        } finally {
1201:                            if (!possibleMatch.nodeSet.mustResolve)
1202:                                possibleMatch.cleanUp();
1203:                        }
1204:                    }
1205:                    if (mustResolve)
1206:                        this .lookupEnvironment.completeTypeBindings();
1207:
1208:                    // create hierarchy resolver if needed
1209:                    IType focusType = getFocusType();
1210:                    if (focusType == null) {
1211:                        this .hierarchyResolver = null;
1212:                    } else if (!createHierarchyResolver(focusType,
1213:                            possibleMatches)) {
1214:                        // focus type is not visible, use the super type names instead of the bindings
1215:                        if (computeSuperTypeNames(focusType) == null)
1216:                            return;
1217:                    }
1218:                } catch (AbortCompilation e) {
1219:                    bindingsWereCreated = false;
1220:                }
1221:
1222:                if (!mustResolve) {
1223:                    return;
1224:                }
1225:
1226:                // possible match resolution
1227:                for (int i = 0; i < this .numberOfMatches; i++) {
1228:                    if (this .progressMonitor != null
1229:                            && this .progressMonitor.isCanceled())
1230:                        throw new OperationCanceledException();
1231:                    PossibleMatch possibleMatch = this .matchesToProcess[i];
1232:                    this .matchesToProcess[i] = null; // release reference to processed possible match
1233:                    try {
1234:                        process(possibleMatch, bindingsWereCreated);
1235:                    } catch (AbortCompilation e) {
1236:                        // problem with class path: it could not find base classes
1237:                        // continue and try next matching openable reporting innacurate matches (since bindings will be null)
1238:                        bindingsWereCreated = false;
1239:                    } catch (JavaModelException e) {
1240:                        // problem with class path: it could not find base classes
1241:                        // continue and try next matching openable reporting innacurate matches (since bindings will be null)
1242:                        bindingsWereCreated = false;
1243:                    } finally {
1244:                        if (this .progressMonitor != null) {
1245:                            this .progressWorked++;
1246:                            if ((this .progressWorked % this .progressStep) == 0)
1247:                                this .progressMonitor.worked(this .progressStep);
1248:                        }
1249:                        if (this .options.verbose)
1250:                            System.out
1251:                                    .println(Messages
1252:                                            .bind(
1253:                                                    Messages.compilation_done,
1254:                                                    new String[] {
1255:                                                            String
1256:                                                                    .valueOf(i + 1),
1257:                                                            String
1258:                                                                    .valueOf(this .numberOfMatches),
1259:                                                            new String(
1260:                                                                    possibleMatch.parsedUnit
1261:                                                                            .getFileName()) }));
1262:                        // cleanup compilation unit result
1263:                        possibleMatch.cleanUp();
1264:                    }
1265:                }
1266:            }
1267:
1268:            /**
1269:             * Locate the matches amongst the possible matches.
1270:             */
1271:            protected void locateMatches(JavaProject javaProject,
1272:                    PossibleMatchSet matchSet, int expected)
1273:                    throws CoreException {
1274:                PossibleMatch[] possibleMatches = matchSet
1275:                        .getPossibleMatches(javaProject
1276:                                .getPackageFragmentRoots());
1277:                int length = possibleMatches.length;
1278:                // increase progress from duplicate matches not stored in matchSet while adding...
1279:                if (this .progressMonitor != null && expected > length) {
1280:                    this .progressWorked += expected - length;
1281:                    this .progressMonitor.worked(expected - length);
1282:                }
1283:                // locate matches (processed matches are limited to avoid problem while using VM default memory heap size)
1284:                for (int index = 0; index < length;) {
1285:                    int max = Math.min(MAX_AT_ONCE, length - index);
1286:                    locateMatches(javaProject, possibleMatches, index, max);
1287:                    index += max;
1288:                }
1289:                this .patternLocator.clear();
1290:            }
1291:
1292:            /**
1293:             * Locate the matches in the given files and report them using the search requestor. 
1294:             */
1295:            public void locateMatches(SearchDocument[] searchDocuments)
1296:                    throws CoreException {
1297:                if (this .patternLocator == null)
1298:                    return;
1299:                int docsLength = searchDocuments.length;
1300:                if (BasicSearchEngine.VERBOSE) {
1301:                    System.out.println("Locating matches in documents ["); //$NON-NLS-1$
1302:                    for (int i = 0; i < docsLength; i++)
1303:                        System.out.println("\t" + searchDocuments[i]); //$NON-NLS-1$
1304:                    System.out.println("]"); //$NON-NLS-1$
1305:                }
1306:
1307:                // init infos for progress increasing
1308:                int n = docsLength < 1000 ? Math.min(Math.max(
1309:                        docsLength / 200 + 1, 2), 4) : 5 * (docsLength / 1000);
1310:                this .progressStep = docsLength < n ? 1 : docsLength / n; // step should not be 0
1311:                this .progressWorked = 0;
1312:
1313:                // extract working copies
1314:                ArrayList copies = new ArrayList();
1315:                for (int i = 0; i < docsLength; i++) {
1316:                    SearchDocument document = searchDocuments[i];
1317:                    if (document instanceof  WorkingCopyDocument) {
1318:                        copies
1319:                                .add(((WorkingCopyDocument) document).workingCopy);
1320:                    }
1321:                }
1322:                int copiesLength = copies.size();
1323:                this .workingCopies = new org.eclipse.jdt.core.ICompilationUnit[copiesLength];
1324:                copies.toArray(this .workingCopies);
1325:
1326:                JavaModelManager manager = JavaModelManager
1327:                        .getJavaModelManager();
1328:                this .bindings = new SimpleLookupTable();
1329:                try {
1330:                    // optimize access to zip files during search operation
1331:                    manager.cacheZipFiles();
1332:
1333:                    // initialize handle factory (used as a cache of handles so as to optimize space)
1334:                    if (this .handleFactory == null)
1335:                        this .handleFactory = new HandleFactory();
1336:
1337:                    if (this .progressMonitor != null) {
1338:                        this .progressMonitor.beginTask(
1339:                                "", searchDocuments.length); //$NON-NLS-1$
1340:                    }
1341:
1342:                    // initialize pattern for polymorphic search (ie. method reference pattern)
1343:                    this .patternLocator.initializePolymorphicSearch(this );
1344:
1345:                    JavaProject previousJavaProject = null;
1346:                    PossibleMatchSet matchSet = new PossibleMatchSet();
1347:                    Util.sort(searchDocuments, new Util.Comparer() {
1348:                        public int compare(Object a, Object b) {
1349:                            return ((SearchDocument) a).getPath().compareTo(
1350:                                    ((SearchDocument) b).getPath());
1351:                        }
1352:                    });
1353:                    int displayed = 0; // progress worked displayed
1354:                    String previousPath = null;
1355:                    for (int i = 0; i < docsLength; i++) {
1356:                        if (this .progressMonitor != null
1357:                                && this .progressMonitor.isCanceled()) {
1358:                            throw new OperationCanceledException();
1359:                        }
1360:
1361:                        // skip duplicate paths
1362:                        SearchDocument searchDocument = searchDocuments[i];
1363:                        searchDocuments[i] = null; // free current document
1364:                        String pathString = searchDocument.getPath();
1365:                        if (i > 0 && pathString.equals(previousPath)) {
1366:                            if (this .progressMonitor != null) {
1367:                                this .progressWorked++;
1368:                                if ((this .progressWorked % this .progressStep) == 0)
1369:                                    this .progressMonitor
1370:                                            .worked(this .progressStep);
1371:                            }
1372:                            displayed++;
1373:                            continue;
1374:                        }
1375:                        previousPath = pathString;
1376:
1377:                        Openable openable;
1378:                        org.eclipse.jdt.core.ICompilationUnit workingCopy = null;
1379:                        if (searchDocument instanceof  WorkingCopyDocument) {
1380:                            workingCopy = ((WorkingCopyDocument) searchDocument).workingCopy;
1381:                            openable = (Openable) workingCopy;
1382:                        } else {
1383:                            openable = this .handleFactory.createOpenable(
1384:                                    pathString, this .scope);
1385:                        }
1386:                        if (openable == null) {
1387:                            if (this .progressMonitor != null) {
1388:                                this .progressWorked++;
1389:                                if ((this .progressWorked % this .progressStep) == 0)
1390:                                    this .progressMonitor
1391:                                            .worked(this .progressStep);
1392:                            }
1393:                            displayed++;
1394:                            continue; // match is outside classpath
1395:                        }
1396:
1397:                        // create new parser and lookup environment if this is a new project
1398:                        IResource resource = null;
1399:                        JavaProject javaProject = (JavaProject) openable
1400:                                .getJavaProject();
1401:                        resource = workingCopy != null ? workingCopy
1402:                                .getResource() : openable.getResource();
1403:                        if (resource == null)
1404:                            resource = javaProject.getProject(); // case of a file in an external jar
1405:                        if (!javaProject.equals(previousJavaProject)) {
1406:                            // locate matches in previous project
1407:                            if (previousJavaProject != null) {
1408:                                try {
1409:                                    locateMatches(previousJavaProject,
1410:                                            matchSet, i - displayed);
1411:                                    displayed = i;
1412:                                } catch (JavaModelException e) {
1413:                                    // problem with classpath in this project -> skip it
1414:                                }
1415:                                matchSet.reset();
1416:                            }
1417:                            previousJavaProject = javaProject;
1418:                        }
1419:                        matchSet
1420:                                .add(new PossibleMatch(
1421:                                        this ,
1422:                                        resource,
1423:                                        openable,
1424:                                        searchDocument,
1425:                                        ((InternalSearchPattern) this .pattern).mustResolve));
1426:                    }
1427:
1428:                    // last project
1429:                    if (previousJavaProject != null) {
1430:                        try {
1431:                            locateMatches(previousJavaProject, matchSet,
1432:                                    docsLength - displayed);
1433:                        } catch (JavaModelException e) {
1434:                            // problem with classpath in last project -> ignore
1435:                        }
1436:                    }
1437:
1438:                } finally {
1439:                    if (this .progressMonitor != null)
1440:                        this .progressMonitor.done();
1441:                    if (this .nameEnvironment != null)
1442:                        this .nameEnvironment.cleanup();
1443:                    manager.flushZipFiles();
1444:                    this .bindings = null;
1445:                }
1446:            }
1447:
1448:            /**
1449:             * Locates the package declarations corresponding to this locator's pattern. 
1450:             */
1451:            public void locatePackageDeclarations(SearchParticipant participant)
1452:                    throws CoreException {
1453:                locatePackageDeclarations(this .pattern, participant);
1454:            }
1455:
1456:            /**
1457:             * Locates the package declarations corresponding to the search pattern. 
1458:             */
1459:            protected void locatePackageDeclarations(
1460:                    SearchPattern searchPattern, SearchParticipant participant)
1461:                    throws CoreException {
1462:                if (searchPattern instanceof  OrPattern) {
1463:                    SearchPattern[] patterns = ((OrPattern) searchPattern).patterns;
1464:                    for (int i = 0, length = patterns.length; i < length; i++)
1465:                        locatePackageDeclarations(patterns[i], participant);
1466:                } else if (searchPattern instanceof  PackageDeclarationPattern) {
1467:                    IJavaElement focus = ((InternalSearchPattern) searchPattern).focus;
1468:                    if (focus != null) {
1469:                        if (encloses(focus)) {
1470:                            SearchMatch match = new PackageDeclarationMatch(
1471:                                    focus
1472:                                            .getAncestor(IJavaElement.PACKAGE_FRAGMENT),
1473:                                    SearchMatch.A_ACCURATE, -1, -1,
1474:                                    participant, focus.getResource());
1475:                            report(match);
1476:                        }
1477:                        return;
1478:                    }
1479:                    PackageDeclarationPattern pkgPattern = (PackageDeclarationPattern) searchPattern;
1480:                    boolean isWorkspaceScope = this .scope == JavaModelManager
1481:                            .getJavaModelManager().getWorkspaceScope();
1482:                    IPath[] scopeProjectsAndJars = isWorkspaceScope ? null
1483:                            : this .scope.enclosingProjectsAndJars();
1484:                    int scopeLength = isWorkspaceScope ? 0
1485:                            : scopeProjectsAndJars.length;
1486:                    IJavaProject[] projects = JavaModelManager
1487:                            .getJavaModelManager().getJavaModel()
1488:                            .getJavaProjects();
1489:                    SimpleSet packages = new SimpleSet();
1490:                    for (int i = 0, length = projects.length; i < length; i++) {
1491:                        IJavaProject javaProject = projects[i];
1492:                        // Verify that project belongs to the scope
1493:                        if (!isWorkspaceScope) {
1494:                            boolean found = false;
1495:                            for (int j = 0; j < scopeLength; j++) {
1496:                                if (javaProject.getPath().equals(
1497:                                        scopeProjectsAndJars[j])) {
1498:                                    found = true;
1499:                                    break;
1500:                                }
1501:                            }
1502:                            if (!found)
1503:                                continue;
1504:                        }
1505:                        // Get all project package fragment names
1506:                        this .nameLookup = ((JavaProject) projects[i])
1507:                                .newNameLookup(this .workingCopies);
1508:                        IPackageFragment[] packageFragments = this .nameLookup
1509:                                .findPackageFragments(new String(
1510:                                        pkgPattern.pkgName), false, true);
1511:                        int pLength = packageFragments == null ? 0
1512:                                : packageFragments.length;
1513:                        // Report matches avoiding duplicate names
1514:                        for (int p = 0; p < pLength; p++) {
1515:                            IPackageFragment fragment = packageFragments[p];
1516:                            if (packages.addIfNotIncluded(fragment) == null)
1517:                                continue;
1518:                            if (encloses(fragment)) {
1519:                                IResource resource = fragment.getResource();
1520:                                if (resource == null) // case of a file in an external jar
1521:                                    resource = javaProject.getProject();
1522:                                try {
1523:                                    if (encloses(fragment)) {
1524:                                        SearchMatch match = new PackageDeclarationMatch(
1525:                                                fragment,
1526:                                                SearchMatch.A_ACCURATE, -1, -1,
1527:                                                participant, resource);
1528:                                        report(match);
1529:                                    }
1530:                                } catch (JavaModelException e) {
1531:                                    throw e;
1532:                                } catch (CoreException e) {
1533:                                    throw new JavaModelException(e);
1534:                                }
1535:                            }
1536:                        }
1537:                    }
1538:                }
1539:            }
1540:
1541:            //*/
1542:            protected IType lookupType(ReferenceBinding typeBinding) {
1543:                if (typeBinding == null)
1544:                    return null;
1545:
1546:                char[] packageName = typeBinding.qualifiedPackageName();
1547:                IPackageFragment[] pkgs = this .nameLookup
1548:                        .findPackageFragments(
1549:                                (packageName == null || packageName.length == 0) ? IPackageFragment.DEFAULT_PACKAGE_NAME
1550:                                        : new String(packageName), false);
1551:
1552:                // iterate type lookup in each package fragment
1553:                char[] sourceName = typeBinding.qualifiedSourceName();
1554:                String typeName = new String(sourceName);
1555:                int acceptFlag = 0;
1556:                if (typeBinding.isAnnotationType()) {
1557:                    acceptFlag = NameLookup.ACCEPT_ANNOTATIONS;
1558:                } else if (typeBinding.isEnum()) {
1559:                    acceptFlag = NameLookup.ACCEPT_ENUMS;
1560:                } else if (typeBinding.isInterface()) {
1561:                    acceptFlag = NameLookup.ACCEPT_INTERFACES;
1562:                } else if (typeBinding.isClass()) {
1563:                    acceptFlag = NameLookup.ACCEPT_CLASSES;
1564:                }
1565:                if (pkgs != null) {
1566:                    for (int i = 0, length = pkgs.length; i < length; i++) {
1567:                        IType type = this .nameLookup
1568:                                .findType(typeName, pkgs[i], false, acceptFlag,
1569:                                        true/*consider secondary types*/);
1570:                        if (type != null)
1571:                            return type;
1572:                    }
1573:                }
1574:
1575:                // search inside enclosing element
1576:                char[][] qualifiedName = CharOperation.splitOn('.', sourceName);
1577:                int length = qualifiedName.length;
1578:                if (length == 0)
1579:                    return null;
1580:
1581:                IType type = createTypeHandle(new String(qualifiedName[0])); // find the top-level type
1582:                if (type == null)
1583:                    return null;
1584:
1585:                for (int i = 1; i < length; i++) {
1586:                    type = type.getType(new String(qualifiedName[i]));
1587:                    if (type == null)
1588:                        return null;
1589:                }
1590:                if (type.exists())
1591:                    return type;
1592:                return null;
1593:            }
1594:
1595:            public SearchMatch newDeclarationMatch(IJavaElement element,
1596:                    Binding binding, int accuracy, int offset, int length) {
1597:                SearchParticipant participant = getParticipant();
1598:                IResource resource = this .currentPossibleMatch.resource;
1599:                return newDeclarationMatch(element, binding, accuracy, offset,
1600:                        length, participant, resource);
1601:            }
1602:
1603:            public SearchMatch newDeclarationMatch(IJavaElement element,
1604:                    Binding binding, int accuracy, int offset, int length,
1605:                    SearchParticipant participant, IResource resource) {
1606:                switch (element.getElementType()) {
1607:                case IJavaElement.PACKAGE_FRAGMENT:
1608:                    return new PackageDeclarationMatch(element, accuracy,
1609:                            offset, length, participant, resource);
1610:                case IJavaElement.TYPE:
1611:                    return new TypeDeclarationMatch(binding == null ? element
1612:                            : ((JavaElement) element).resolved(binding),
1613:                            accuracy, offset, length, participant, resource);
1614:                case IJavaElement.FIELD:
1615:                    return new FieldDeclarationMatch(binding == null ? element
1616:                            : ((JavaElement) element).resolved(binding),
1617:                            accuracy, offset, length, participant, resource);
1618:                case IJavaElement.METHOD:
1619:                    return new MethodDeclarationMatch(binding == null ? element
1620:                            : ((JavaElement) element).resolved(binding),
1621:                            accuracy, offset, length, participant, resource);
1622:                case IJavaElement.LOCAL_VARIABLE:
1623:                    return new LocalVariableDeclarationMatch(element, accuracy,
1624:                            offset, length, participant, resource);
1625:                case IJavaElement.PACKAGE_DECLARATION:
1626:                    return new PackageDeclarationMatch(element, accuracy,
1627:                            offset, length, participant, resource);
1628:                case IJavaElement.TYPE_PARAMETER:
1629:                    return new TypeParameterDeclarationMatch(element, accuracy,
1630:                            offset, length, participant, resource);
1631:                default:
1632:                    return null;
1633:                }
1634:            }
1635:
1636:            public SearchMatch newFieldReferenceMatch(
1637:                    IJavaElement enclosingElement, Binding enclosingBinding,
1638:                    int accuracy, int offset, int length, ASTNode reference) {
1639:                int bits = reference.bits;
1640:                boolean isCoupoundAssigned = (bits & ASTNode.IsCompoundAssigned) != 0;
1641:                boolean isReadAccess = isCoupoundAssigned
1642:                        || (bits & ASTNode.IsStrictlyAssigned) == 0;
1643:                boolean isWriteAccess = isCoupoundAssigned
1644:                        || (bits & ASTNode.IsStrictlyAssigned) != 0;
1645:                boolean insideDocComment = (bits & ASTNode.InsideJavadoc) != 0;
1646:                SearchParticipant participant = getParticipant();
1647:                IResource resource = this .currentPossibleMatch.resource;
1648:                if (enclosingBinding != null)
1649:                    enclosingElement = ((JavaElement) enclosingElement)
1650:                            .resolved(enclosingBinding);
1651:                return new FieldReferenceMatch(enclosingElement, accuracy,
1652:                        offset, length, isReadAccess, isWriteAccess,
1653:                        insideDocComment, participant, resource);
1654:            }
1655:
1656:            public SearchMatch newLocalVariableReferenceMatch(
1657:                    IJavaElement enclosingElement, int accuracy, int offset,
1658:                    int length, ASTNode reference) {
1659:                int bits = reference.bits;
1660:                boolean isCoupoundAssigned = (bits & ASTNode.IsCompoundAssigned) != 0;
1661:                boolean isReadAccess = isCoupoundAssigned
1662:                        || (bits & ASTNode.IsStrictlyAssigned) == 0;
1663:                boolean isWriteAccess = isCoupoundAssigned
1664:                        || (bits & ASTNode.IsStrictlyAssigned) != 0;
1665:                boolean insideDocComment = (bits & ASTNode.InsideJavadoc) != 0;
1666:                SearchParticipant participant = getParticipant();
1667:                IResource resource = this .currentPossibleMatch.resource;
1668:                return new LocalVariableReferenceMatch(enclosingElement,
1669:                        accuracy, offset, length, isReadAccess, isWriteAccess,
1670:                        insideDocComment, participant, resource);
1671:            }
1672:
1673:            public SearchMatch newMethodReferenceMatch(
1674:                    IJavaElement enclosingElement, Binding enclosingBinding,
1675:                    int accuracy, int offset, int length,
1676:                    boolean isConstructor, boolean isSynthetic,
1677:                    ASTNode reference) {
1678:                SearchParticipant participant = getParticipant();
1679:                IResource resource = this .currentPossibleMatch.resource;
1680:                boolean insideDocComment = (reference.bits & ASTNode.InsideJavadoc) != 0;
1681:                if (enclosingBinding != null)
1682:                    enclosingElement = ((JavaElement) enclosingElement)
1683:                            .resolved(enclosingBinding);
1684:                boolean isOverridden = (accuracy & PatternLocator.SUPER_INVOCATION_FLAVOR) != 0;
1685:                return new MethodReferenceMatch(enclosingElement, accuracy,
1686:                        offset, length, isConstructor, isSynthetic,
1687:                        isOverridden, insideDocComment, participant, resource);
1688:            }
1689:
1690:            public SearchMatch newPackageReferenceMatch(
1691:                    IJavaElement enclosingElement, int accuracy, int offset,
1692:                    int length, ASTNode reference) {
1693:                SearchParticipant participant = getParticipant();
1694:                IResource resource = this .currentPossibleMatch.resource;
1695:                boolean insideDocComment = (reference.bits & ASTNode.InsideJavadoc) != 0;
1696:                return new PackageReferenceMatch(enclosingElement, accuracy,
1697:                        offset, length, insideDocComment, participant, resource);
1698:            }
1699:
1700:            public SearchMatch newTypeParameterReferenceMatch(
1701:                    IJavaElement enclosingElement, int accuracy, int offset,
1702:                    int length, ASTNode reference) {
1703:                int bits = reference.bits;
1704:                boolean insideDocComment = (bits & ASTNode.InsideJavadoc) != 0;
1705:                SearchParticipant participant = getParticipant();
1706:                IResource resource = this .currentPossibleMatch.resource;
1707:                return new TypeParameterReferenceMatch(enclosingElement,
1708:                        accuracy, offset, length, insideDocComment,
1709:                        participant, resource);
1710:            }
1711:
1712:            public TypeReferenceMatch newTypeReferenceMatch(
1713:                    IJavaElement enclosingElement, Binding enclosingBinding,
1714:                    int accuracy, int offset, int length, ASTNode reference) {
1715:                SearchParticipant participant = getParticipant();
1716:                IResource resource = this .currentPossibleMatch.resource;
1717:                boolean insideDocComment = (reference.bits & ASTNode.InsideJavadoc) != 0;
1718:                if (enclosingBinding != null)
1719:                    enclosingElement = ((JavaElement) enclosingElement)
1720:                            .resolved(enclosingBinding);
1721:                return new TypeReferenceMatch(enclosingElement, accuracy,
1722:                        offset, length, insideDocComment, participant, resource);
1723:            }
1724:
1725:            public TypeReferenceMatch newTypeReferenceMatch(
1726:                    IJavaElement enclosingElement, Binding enclosingBinding,
1727:                    int accuracy, ASTNode reference) {
1728:                return newTypeReferenceMatch(enclosingElement,
1729:                        enclosingBinding, accuracy, reference.sourceStart,
1730:                        reference.sourceEnd - reference.sourceStart + 1,
1731:                        reference);
1732:            }
1733:
1734:            /**
1735:             * Add the possibleMatch to the loop
1736:             *  ->  build compilation unit declarations, their bindings and record their results.
1737:             */
1738:            protected boolean parseAndBuildBindings(
1739:                    PossibleMatch possibleMatch, boolean mustResolve)
1740:                    throws CoreException {
1741:                if (this .progressMonitor != null
1742:                        && this .progressMonitor.isCanceled())
1743:                    throw new OperationCanceledException();
1744:
1745:                try {
1746:                    if (BasicSearchEngine.VERBOSE)
1747:                        System.out
1748:                                .println("Parsing " + possibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
1749:
1750:                    this .parser.nodeSet = possibleMatch.nodeSet;
1751:                    CompilationResult unitResult = new CompilationResult(
1752:                            possibleMatch, 1, 1,
1753:                            this .options.maxProblemsPerUnit);
1754:                    CompilationUnitDeclaration parsedUnit = this .parser
1755:                            .dietParse(possibleMatch, unitResult);
1756:                    if (parsedUnit != null) {
1757:                        if (!parsedUnit.isEmpty()) {
1758:                            if (mustResolve) {
1759:                                this .lookupEnvironment
1760:                                        .buildTypeBindings(parsedUnit, null /*no access restriction*/);
1761:                            }
1762:                            if (hasAlreadyDefinedType(parsedUnit))
1763:                                return false; // skip type has it is hidden so not visible
1764:                            getMethodBodies(parsedUnit, possibleMatch.nodeSet);
1765:                            if (this .patternLocator.mayBeGeneric
1766:                                    && !mustResolve
1767:                                    && possibleMatch.nodeSet.mustResolve) {
1768:                                // special case: possible match node set force resolution although pattern does not
1769:                                // => we need to build types for this compilation unit
1770:                                this .lookupEnvironment
1771:                                        .buildTypeBindings(parsedUnit, null /*no access restriction*/);
1772:                            }
1773:                        }
1774:
1775:                        // add the possibleMatch with its parsedUnit to matchesToProcess
1776:                        possibleMatch.parsedUnit = parsedUnit;
1777:                        int size = this .matchesToProcess.length;
1778:                        if (this .numberOfMatches == size)
1779:                            System
1780:                                    .arraycopy(
1781:                                            this .matchesToProcess,
1782:                                            0,
1783:                                            this .matchesToProcess = new PossibleMatch[size == 0 ? 1
1784:                                                    : size * 2], 0,
1785:                                            this .numberOfMatches);
1786:                        this .matchesToProcess[this .numberOfMatches++] = possibleMatch;
1787:                    }
1788:                } finally {
1789:                    this .parser.nodeSet = null;
1790:                }
1791:                return true;
1792:            }
1793:
1794:            /*
1795:             * Process a compilation unit already parsed and build.
1796:             */
1797:            protected void process(PossibleMatch possibleMatch,
1798:                    boolean bindingsWereCreated) throws CoreException {
1799:                this .currentPossibleMatch = possibleMatch;
1800:                CompilationUnitDeclaration unit = possibleMatch.parsedUnit;
1801:                try {
1802:                    if (unit.isEmpty()) {
1803:                        if (this .currentPossibleMatch.openable instanceof  ClassFile) {
1804:                            ClassFile classFile = (ClassFile) this .currentPossibleMatch.openable;
1805:                            IBinaryType info = getBinaryInfo(classFile,
1806:                                    this .currentPossibleMatch.resource);
1807:                            if (info != null) {
1808:                                boolean mayBeGeneric = this .patternLocator.mayBeGeneric;
1809:                                this .patternLocator.mayBeGeneric = false; // there's no longer generics in class files
1810:                                try {
1811:                                    new ClassFileMatchLocator().locateMatches(
1812:                                            this , classFile, info);
1813:                                } finally {
1814:                                    this .patternLocator.mayBeGeneric = mayBeGeneric;
1815:                                }
1816:                            }
1817:                        }
1818:                        return;
1819:                    }
1820:                    if (hasAlreadyDefinedType(unit))
1821:                        return; // skip type has it is hidden so not visible
1822:
1823:                    // Move getMethodBodies to #parseAndBuildings(...) method to allow possible match resolution management
1824:                    //getMethodBodies(unit);
1825:
1826:                    boolean mustResolve = (((InternalSearchPattern) this .pattern).mustResolve || possibleMatch.nodeSet.mustResolve);
1827:                    if (bindingsWereCreated && mustResolve) {
1828:                        if (unit.types != null) {
1829:                            if (BasicSearchEngine.VERBOSE)
1830:                                System.out
1831:                                        .println("Resolving " + this .currentPossibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
1832:
1833:                            this .lookupEnvironment.unitBeingCompleted = unit;
1834:                            reduceParseTree(unit);
1835:
1836:                            if (unit.scope != null) {
1837:                                // fault in fields & methods
1838:                                unit.scope.faultInTypes();
1839:                            }
1840:                            unit.resolve();
1841:                        } else if (unit.isPackageInfo()) {
1842:                            if (BasicSearchEngine.VERBOSE)
1843:                                System.out
1844:                                        .println("Resolving " + this .currentPossibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
1845:                            unit.resolve();
1846:                        }
1847:                    }
1848:                    reportMatching(unit, mustResolve);
1849:                } catch (AbortCompilation e) {
1850:                    // could not resolve: report inaccurate matches
1851:                    reportMatching(unit, false); // do not resolve when cu has errors
1852:                    if (!(e instanceof  AbortCompilationUnit)) {
1853:                        // problem with class path
1854:                        throw e;
1855:                    }
1856:                } finally {
1857:                    this .lookupEnvironment.unitBeingCompleted = null;
1858:                    this .currentPossibleMatch = null;
1859:                }
1860:            }
1861:
1862:            protected void purgeMethodStatements(TypeDeclaration type,
1863:                    boolean checkEachMethod) {
1864:                checkEachMethod = checkEachMethod
1865:                        && this .currentPossibleMatch.nodeSet.hasPossibleNodes(
1866:                                type.declarationSourceStart,
1867:                                type.declarationSourceEnd);
1868:                AbstractMethodDeclaration[] methods = type.methods;
1869:                if (methods != null) {
1870:                    if (checkEachMethod) {
1871:                        for (int j = 0, length = methods.length; j < length; j++) {
1872:                            AbstractMethodDeclaration method = methods[j];
1873:                            if (!this .currentPossibleMatch.nodeSet
1874:                                    .hasPossibleNodes(
1875:                                            method.declarationSourceStart,
1876:                                            method.declarationSourceEnd)) {
1877:                                method.statements = null;
1878:                                method.javadoc = null;
1879:                            }
1880:                        }
1881:                    } else {
1882:                        for (int j = 0, length = methods.length; j < length; j++) {
1883:                            methods[j].statements = null;
1884:                            methods[j].javadoc = null;
1885:                        }
1886:                    }
1887:                }
1888:
1889:                TypeDeclaration[] memberTypes = type.memberTypes;
1890:                if (memberTypes != null)
1891:                    for (int i = 0, l = memberTypes.length; i < l; i++)
1892:                        purgeMethodStatements(memberTypes[i], checkEachMethod);
1893:            }
1894:
1895:            /**
1896:             * Called prior to the unit being resolved. Reduce the parse tree where possible.
1897:             */
1898:            protected void reduceParseTree(CompilationUnitDeclaration unit) {
1899:                // remove statements from methods that have no possible matching nodes
1900:                TypeDeclaration[] types = unit.types;
1901:                for (int i = 0, l = types.length; i < l; i++)
1902:                    purgeMethodStatements(types[i], true);
1903:            }
1904:
1905:            public SearchParticipant getParticipant() {
1906:                return this .currentPossibleMatch.document.getParticipant();
1907:            }
1908:
1909:            protected void report(SearchMatch match) throws CoreException {
1910:                if (match == null) {
1911:                    if (BasicSearchEngine.VERBOSE) {
1912:                        System.out.println("Cannot report a null match!!!"); //$NON-NLS-1$
1913:                    }
1914:                    return;
1915:                }
1916:                long start = -1;
1917:                if (BasicSearchEngine.VERBOSE) {
1918:                    start = System.currentTimeMillis();
1919:                    System.out.println("Reporting match"); //$NON-NLS-1$
1920:                    System.out.println("\tResource: " + match.getResource());//$NON-NLS-1$
1921:                    System.out
1922:                            .println("\tPositions: [offset=" + match.getOffset() + ", length=" + match.getLength() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1923:                    try {
1924:                        if (this .parser != null
1925:                                && match.getOffset() > 0
1926:                                && match.getLength() > 0
1927:                                && !(match.getElement() instanceof  BinaryMember)) {
1928:                            String selection = new String(
1929:                                    this .parser.scanner.source, match
1930:                                            .getOffset(), match.getLength());
1931:                            System.out
1932:                                    .println("\tSelection: -->" + selection + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
1933:                        }
1934:                    } catch (Exception e) {
1935:                        // it's just for debug purposes... ignore all exceptions in this area
1936:                    }
1937:                    try {
1938:                        JavaElement javaElement = (JavaElement) match
1939:                                .getElement();
1940:                        System.out
1941:                                .println("\tJava element: " + javaElement.toStringWithAncestors()); //$NON-NLS-1$
1942:                        if (!javaElement.exists()) {
1943:                            System.out
1944:                                    .println("\t\tWARNING: this element does NOT exist!"); //$NON-NLS-1$
1945:                        }
1946:                    } catch (Exception e) {
1947:                        // it's just for debug purposes... ignore all exceptions in this area
1948:                    }
1949:                    if (match instanceof  TypeReferenceMatch) {
1950:                        try {
1951:                            TypeReferenceMatch typeRefMatch = (TypeReferenceMatch) match;
1952:                            JavaElement local = (JavaElement) typeRefMatch
1953:                                    .getLocalElement();
1954:                            if (local != null) {
1955:                                System.out
1956:                                        .println("\tLocal element: " + local.toStringWithAncestors()); //$NON-NLS-1$
1957:                            }
1958:                            IJavaElement[] others = typeRefMatch
1959:                                    .getOtherElements();
1960:                            if (others != null) {
1961:                                int length = others.length;
1962:                                if (length > 0) {
1963:                                    System.out.println("\tOther elements:"); //$NON-NLS-1$
1964:                                    for (int i = 0; i < length; i++) {
1965:                                        JavaElement other = (JavaElement) others[i];
1966:                                        System.out
1967:                                                .println("\t\t- " + other.toStringWithAncestors()); //$NON-NLS-1$
1968:                                    }
1969:                                }
1970:                            }
1971:                        } catch (Exception e) {
1972:                            // it's just for debug purposes... ignore all exceptions in this area
1973:                        }
1974:                    }
1975:                    System.out
1976:                            .println(match.getAccuracy() == SearchMatch.A_ACCURATE ? "\tAccuracy: EXACT_MATCH" //$NON-NLS-1$
1977:                                    : "\tAccuracy: POTENTIAL_MATCH"); //$NON-NLS-1$
1978:                    System.out.print("\tRule: "); //$NON-NLS-1$
1979:                    if (match.isExact()) {
1980:                        System.out.print("EXACT"); //$NON-NLS-1$
1981:                    } else if (match.isEquivalent()) {
1982:                        System.out.print("EQUIVALENT"); //$NON-NLS-1$
1983:                    } else if (match.isErasure()) {
1984:                        System.out.print("ERASURE"); //$NON-NLS-1$
1985:                    } else {
1986:                        System.out.print("INVALID RULE"); //$NON-NLS-1$
1987:                    }
1988:                    if (match instanceof  MethodReferenceMatch) {
1989:                        MethodReferenceMatch methodReferenceMatch = (MethodReferenceMatch) match;
1990:                        if (methodReferenceMatch.isSuperInvocation()) {
1991:                            System.out.print("+SUPER INVOCATION"); //$NON-NLS-1$
1992:                        }
1993:                        if (methodReferenceMatch.isImplicit()) {
1994:                            System.out.print("+IMPLICIT"); //$NON-NLS-1$
1995:                        }
1996:                        if (methodReferenceMatch.isSynthetic()) {
1997:                            System.out.print("+SYNTHETIC"); //$NON-NLS-1$
1998:                        }
1999:                    }
2000:                    System.out.println("\n\tRaw: " + match.isRaw()); //$NON-NLS-1$
2001:                }
2002:                this .requestor.acceptSearchMatch(match);
2003:                if (BasicSearchEngine.VERBOSE)
2004:                    this .resultCollectorTime += System.currentTimeMillis()
2005:                            - start;
2006:            }
2007:
2008:            /**
2009:             * Finds the accurate positions of the sequence of tokens given by qualifiedName
2010:             * in the source and reports a reference to this this qualified name
2011:             * to the search requestor.
2012:             */
2013:            protected void reportAccurateTypeReference(SearchMatch match,
2014:                    ASTNode typeRef, char[] name) throws CoreException {
2015:                if (match.getRule() == 0)
2016:                    return;
2017:                if (!encloses((IJavaElement) match.getElement()))
2018:                    return;
2019:
2020:                // Compute source positions of the qualified reference 
2021:                int sourceStart = typeRef.sourceStart;
2022:                int sourceEnd = typeRef.sourceEnd;
2023:                Scanner scanner = this .parser.scanner;
2024:                scanner.setSource(this .currentPossibleMatch.getContents());
2025:                scanner.resetTo(sourceStart, sourceEnd);
2026:
2027:                int token = -1;
2028:                int currentPosition;
2029:                do {
2030:                    currentPosition = scanner.currentPosition;
2031:                    try {
2032:                        token = scanner.getNextToken();
2033:                    } catch (InvalidInputException e) {
2034:                        // ignore
2035:                    }
2036:                    if (token == TerminalTokens.TokenNameIdentifier
2037:                            && this .pattern.matchesName(name, scanner
2038:                                    .getCurrentTokenSource())) {
2039:                        int length = scanner.currentPosition - currentPosition;
2040:                        match.setOffset(currentPosition);
2041:                        match.setLength(length);
2042:                        report(match);
2043:                        return;
2044:                    }
2045:                } while (token != TerminalTokens.TokenNameEOF);
2046:
2047:                //	Report match
2048:                match.setOffset(sourceStart);
2049:                match.setLength(sourceEnd - sourceStart + 1);
2050:                report(match);
2051:            }
2052:
2053:            /**
2054:             * Finds the accurate positions of the sequence of tokens given by qualifiedName
2055:             * in the source and reports a reference to this parameterized type name
2056:             * to the search requestor.
2057:             * @since 3.1
2058:             */
2059:            protected void reportAccurateParameterizedMethodReference(
2060:                    SearchMatch match, ASTNode statement,
2061:                    TypeReference[] typeArguments) throws CoreException {
2062:                if (match.getRule() == 0)
2063:                    return;
2064:                if (!encloses((IJavaElement) match.getElement()))
2065:                    return;
2066:
2067:                // If there's type arguments, look for end (ie. char '>') of last one.
2068:                int start = match.getOffset();
2069:                if (typeArguments != null && typeArguments.length > 0) {
2070:                    boolean isErasureMatch = (pattern instanceof  OrPattern) ? ((OrPattern) pattern)
2071:                            .isErasureMatch()
2072:                            : ((JavaSearchPattern) pattern).isErasureMatch();
2073:                    if (!isErasureMatch) {
2074:
2075:                        // Initialize scanner
2076:                        Scanner scanner = this .parser.scanner;
2077:                        char[] source = this .currentPossibleMatch.getContents();
2078:                        scanner.setSource(source);
2079:
2080:                        // Search previous opening '<'
2081:                        start = typeArguments[0].sourceStart;
2082:                        int end = statement.sourceEnd;
2083:                        scanner.resetTo(start, end);
2084:                        int lineStart = start;
2085:                        try {
2086:                            linesUp: while (true) {
2087:                                while (scanner.source[scanner.currentPosition] != '\n') {
2088:                                    scanner.currentPosition--;
2089:                                    if (scanner.currentPosition == 0)
2090:                                        break linesUp;
2091:                                }
2092:                                lineStart = scanner.currentPosition + 1;
2093:                                scanner.resetTo(lineStart, end);
2094:                                while (!scanner.atEnd()) {
2095:                                    if (scanner.getNextToken() == TerminalTokens.TokenNameLESS) {
2096:                                        start = scanner
2097:                                                .getCurrentTokenStartPosition();
2098:                                        break linesUp;
2099:                                    }
2100:                                }
2101:                                end = lineStart - 2;
2102:                                scanner.currentPosition = end;
2103:                            }
2104:                        } catch (InvalidInputException ex) {
2105:                            // give up
2106:                        }
2107:                    }
2108:                }
2109:
2110:                // Report match
2111:                match.setOffset(start);
2112:                match.setLength(statement.sourceEnd - start + 1);
2113:                report(match);
2114:            }
2115:
2116:            /**
2117:             * Finds the accurate positions of the sequence of tokens given by qualifiedName
2118:             * in the source and reports a reference to this parameterized type name
2119:             * to the search requestor.
2120:             * @since 3.1
2121:             */
2122:            protected void reportAccurateParameterizedTypeReference(
2123:                    SearchMatch match, TypeReference typeRef, int index,
2124:                    TypeReference[] typeArguments) throws CoreException {
2125:                if (match.getRule() == 0)
2126:                    return;
2127:                if (!encloses((IJavaElement) match.getElement()))
2128:                    return;
2129:
2130:                // If there's type arguments, look for end (ie. char '>') of last one.
2131:                int end = typeRef.sourceEnd;
2132:                if (typeArguments != null) {
2133:                    // Initialize scanner
2134:                    Scanner scanner = this .parser.scanner;
2135:                    char[] source = this .currentPossibleMatch.getContents();
2136:                    scanner.setSource(source);
2137:
2138:                    boolean shouldMatchErasure = (pattern instanceof  OrPattern) ? ((OrPattern) pattern)
2139:                            .isErasureMatch()
2140:                            : ((JavaSearchPattern) pattern).isErasureMatch();
2141:                    boolean hasSignatures = (pattern instanceof  OrPattern) ? ((OrPattern) pattern)
2142:                            .hasSignatures()
2143:                            : ((JavaSearchPattern) pattern).hasSignatures();
2144:                    if (shouldMatchErasure || !hasSignatures) {
2145:                        // if pattern is erasure only, then select the end of the reference
2146:                        if (typeRef instanceof  QualifiedTypeReference
2147:                                && index >= 0) {
2148:                            long[] positions = ((QualifiedTypeReference) typeRef).sourcePositions;
2149:                            end = (int) positions[index];
2150:                        } else if (typeRef instanceof  ArrayTypeReference) {
2151:                            end = ((ArrayTypeReference) typeRef).originalSourceEnd;
2152:                        }
2153:                    } else {
2154:                        // Set scanner position at end of last type argument
2155:                        scanner.resetTo(end, source.length - 1);
2156:                        int depth = 0;
2157:                        for (int i = typeArguments.length - 1; i >= 0; i--) {
2158:                            if (typeArguments[i] != null) {
2159:                                long lastTypeArgInfo = findLastTypeArgumentInfo(typeArguments[i]);
2160:                                depth = (int) (lastTypeArgInfo >>> 32) + 1;
2161:                                scanner.resetTo(((int) lastTypeArgInfo) + 1,
2162:                                        scanner.eofPosition - 1);
2163:                                break;
2164:                            }
2165:                        }
2166:
2167:                        // Now, scan to search next closing '>'
2168:                        while (depth-- > 0) {
2169:                            while (!scanner.atEnd()) {
2170:                                if (scanner.getNextChar() == '>') {
2171:                                    end = scanner.currentPosition - 1;
2172:                                    break;
2173:                                }
2174:                            }
2175:                        }
2176:                    }
2177:                }
2178:
2179:                // Report match
2180:                match.setLength(end - match.getOffset() + 1);
2181:                report(match);
2182:            }
2183:
2184:            /**
2185:             * Finds the accurate positions of each valid token in the source and
2186:             * reports a reference to this token to the search requestor.
2187:             * A token is valid if it has an accuracy which is not -1.
2188:             */
2189:            protected void reportAccurateEnumConstructorReference(
2190:                    SearchMatch match, FieldDeclaration field,
2191:                    AllocationExpression allocation) throws CoreException {
2192:                // Verify that field declaration is really an enum constant
2193:                if (allocation == null || allocation.enumConstant == null) {
2194:                    report(match);
2195:                    return;
2196:                }
2197:
2198:                // Get scan area
2199:                int sourceStart = match.getOffset() + match.getLength();
2200:                if (allocation.arguments != null
2201:                        && allocation.arguments.length > 0) {
2202:                    sourceStart = allocation.arguments[allocation.arguments.length - 1].sourceEnd + 1;
2203:                }
2204:                int sourceEnd = field.declarationSourceEnd;
2205:                if (allocation instanceof  QualifiedAllocationExpression) {
2206:                    QualifiedAllocationExpression qualifiedAllocation = (QualifiedAllocationExpression) allocation;
2207:                    if (qualifiedAllocation.anonymousType != null) {
2208:                        sourceEnd = qualifiedAllocation.anonymousType.sourceStart - 1;
2209:                    }
2210:                }
2211:
2212:                // Scan to find last closing parenthesis
2213:                Scanner scanner = this .parser.scanner;
2214:                scanner.setSource(this .currentPossibleMatch.getContents());
2215:                scanner.resetTo(sourceStart, sourceEnd);
2216:                try {
2217:                    int token = scanner.getNextToken();
2218:                    while (token != TerminalTokens.TokenNameEOF) {
2219:                        if (token == TerminalTokens.TokenNameRPAREN) {
2220:                            sourceEnd = scanner.getCurrentTokenEndPosition();
2221:                        }
2222:                        token = scanner.getNextToken();
2223:                    }
2224:                } catch (InvalidInputException iie) {
2225:                    // give up
2226:                }
2227:
2228:                // Report match
2229:                match.setLength(sourceEnd - match.getOffset() + 1);
2230:                report(match);
2231:            }
2232:
2233:            /**
2234:             * Finds the accurate positions of each valid token in the source and
2235:             * reports a reference to this token to the search requestor.
2236:             * A token is valid if it has an accuracy which is not -1.
2237:             */
2238:            protected void reportAccurateFieldReference(SearchMatch[] matches,
2239:                    QualifiedNameReference qNameRef) throws CoreException {
2240:                if (matches == null)
2241:                    return; // there's nothing to accurate in this case
2242:                int matchesLength = matches.length;
2243:
2244:                int sourceStart = qNameRef.sourceStart;
2245:                int sourceEnd = qNameRef.sourceEnd;
2246:                char[][] tokens = qNameRef.tokens;
2247:
2248:                // compute source positions of the qualified reference 
2249:                Scanner scanner = this .parser.scanner;
2250:                scanner.setSource(this .currentPossibleMatch.getContents());
2251:                scanner.resetTo(sourceStart, sourceEnd);
2252:                int sourceLength = sourceEnd - sourceStart + 1;
2253:
2254:                int refSourceStart = -1, refSourceEnd = -1;
2255:                int length = tokens.length;
2256:                int token = -1;
2257:                int previousValid = -1;
2258:                int i = 0;
2259:                int index = 0;
2260:                do {
2261:                    int currentPosition = scanner.currentPosition;
2262:                    // read token
2263:                    try {
2264:                        token = scanner.getNextToken();
2265:                    } catch (InvalidInputException e) {
2266:                        //ignore
2267:                    }
2268:                    if (token != TerminalTokens.TokenNameEOF) {
2269:                        char[] currentTokenSource = scanner
2270:                                .getCurrentTokenSource();
2271:                        boolean equals = false;
2272:                        while (i < length
2273:                                && !(equals = this .pattern.matchesName(
2274:                                        tokens[i++], currentTokenSource))) {/*empty*/
2275:                        }
2276:                        if (equals
2277:                                && (previousValid == -1 || previousValid == i - 2)) {
2278:                            previousValid = i - 1;
2279:                            if (refSourceStart == -1)
2280:                                refSourceStart = currentPosition;
2281:                            refSourceEnd = scanner.currentPosition - 1;
2282:                        } else {
2283:                            i = 0;
2284:                            refSourceStart = -1;
2285:                            previousValid = -1;
2286:                        }
2287:                        // read '.'
2288:                        try {
2289:                            token = scanner.getNextToken();
2290:                        } catch (InvalidInputException e) {
2291:                            // ignore
2292:                        }
2293:                    }
2294:                    SearchMatch match = matches[index];
2295:                    if (match != null && match.getRule() != 0) {
2296:                        if (!encloses((IJavaElement) match.getElement()))
2297:                            return;
2298:                        // accept reference
2299:                        if (refSourceStart != -1) {
2300:                            match.setOffset(refSourceStart);
2301:                            match.setLength(refSourceEnd - refSourceStart + 1);
2302:                            report(match);
2303:                        } else {
2304:                            match.setOffset(sourceStart);
2305:                            match.setLength(sourceLength);
2306:                            report(match);
2307:                        }
2308:                        i = 0;
2309:                    }
2310:                    refSourceStart = -1;
2311:                    previousValid = -1;
2312:                    if (index < matchesLength - 1) {
2313:                        index++;
2314:                    }
2315:                } while (token != TerminalTokens.TokenNameEOF);
2316:
2317:            }
2318:
2319:            protected void reportBinaryMemberDeclaration(IResource resource,
2320:                    IMember binaryMember, Binding binaryMemberBinding,
2321:                    IBinaryType info, int accuracy) throws CoreException {
2322:                ClassFile classFile = (ClassFile) binaryMember.getClassFile();
2323:                ISourceRange range = classFile.isOpen() ? binaryMember
2324:                        .getNameRange() : SourceMapper.UNKNOWN_RANGE;
2325:                if (range.getOffset() == -1) {
2326:                    BinaryType type = (BinaryType) classFile.getType();
2327:                    String sourceFileName = type.sourceFileName(info);
2328:                    if (sourceFileName != null) {
2329:                        SourceMapper mapper = classFile.getSourceMapper();
2330:                        if (mapper != null) {
2331:                            char[] contents = mapper.findSource(type,
2332:                                    sourceFileName);
2333:                            if (contents != null)
2334:                                range = mapper.mapSource(type, contents, info,
2335:                                        binaryMember);
2336:                        }
2337:                    }
2338:                }
2339:                if (resource == null)
2340:                    resource = this .currentPossibleMatch.resource;
2341:                SearchMatch match = newDeclarationMatch(binaryMember,
2342:                        binaryMemberBinding, accuracy, range.getOffset(), range
2343:                                .getLength(), getParticipant(), resource);
2344:                report(match);
2345:            }
2346:
2347:            /**
2348:             * Visit the given method declaration and report the nodes that match exactly the
2349:             * search pattern (ie. the ones in the matching nodes set)
2350:             * Note that the method declaration has already been checked.
2351:             */
2352:            protected void reportMatching(TypeDeclaration type,
2353:                    AbstractMethodDeclaration method, IJavaElement parent,
2354:                    int accuracy, boolean typeInHierarchy,
2355:                    MatchingNodeSet nodeSet) throws CoreException {
2356:                IJavaElement enclosingElement = null;
2357:                if (accuracy > -1) {
2358:                    enclosingElement = createHandle(method, parent);
2359:                    if (enclosingElement != null) { // skip if unable to find method
2360:                        // compute source positions of the selector 
2361:                        Scanner scanner = parser.scanner;
2362:                        int nameSourceStart = method.sourceStart;
2363:                        scanner.setSource(this .currentPossibleMatch
2364:                                .getContents());
2365:                        scanner.resetTo(nameSourceStart, method.sourceEnd);
2366:                        try {
2367:                            scanner.getNextToken();
2368:                        } catch (InvalidInputException e) {
2369:                            // ignore
2370:                        }
2371:                        if (encloses(enclosingElement)) {
2372:                            SearchMatch match = null;
2373:                            if (method.isDefaultConstructor()) {
2374:                                // Use type for match associated element as default constructor does not exist in source
2375:                                int offset = type.sourceStart;
2376:                                match = this .patternLocator
2377:                                        .newDeclarationMatch(type, parent,
2378:                                                type.binding, accuracy,
2379:                                                type.sourceEnd - offset + 1,
2380:                                                this );
2381:                            } else {
2382:                                int length = scanner.currentPosition
2383:                                        - nameSourceStart;
2384:                                match = this .patternLocator
2385:                                        .newDeclarationMatch(method,
2386:                                                enclosingElement,
2387:                                                method.binding, accuracy,
2388:                                                length, this );
2389:                            }
2390:                            if (match != null) {
2391:                                report(match);
2392:                            }
2393:                        }
2394:                    }
2395:                }
2396:
2397:                // handle nodes for the local type first
2398:                if ((method.bits & ASTNode.HasLocalType) != 0) {
2399:                    if (enclosingElement == null)
2400:                        enclosingElement = createHandle(method, parent);
2401:                    LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor(
2402:                            enclosingElement, method.binding, nodeSet);
2403:                    try {
2404:                        method.traverse(localDeclarationVisitor,
2405:                                (ClassScope) null);
2406:                    } catch (WrappedCoreException e) {
2407:                        throw e.coreException;
2408:                    }
2409:                }
2410:
2411:                // report the type parameters
2412:                TypeParameter[] typeParameters = method.typeParameters();
2413:                if (typeParameters != null) {
2414:                    if (enclosingElement == null) {
2415:                        enclosingElement = createHandle(method, parent);
2416:                    }
2417:                    reportMatching(typeParameters, enclosingElement, parent,
2418:                            method.binding, nodeSet);
2419:                }
2420:
2421:                // report annotations
2422:                if (method.annotations != null) {
2423:                    if (enclosingElement == null) {
2424:                        enclosingElement = createHandle(method, parent);
2425:                    }
2426:                    reportMatching(method.annotations, enclosingElement,
2427:                            method.binding, nodeSet, true, true);
2428:                }
2429:
2430:                // references in this method
2431:                if (typeInHierarchy) {
2432:                    ASTNode[] nodes = nodeSet.matchingNodes(
2433:                            method.declarationSourceStart,
2434:                            method.declarationSourceEnd);
2435:                    if (nodes != null) {
2436:                        if ((this .matchContainer & PatternLocator.METHOD_CONTAINER) != 0) {
2437:                            if (enclosingElement == null)
2438:                                enclosingElement = createHandle(method, parent);
2439:                            if (encloses(enclosingElement)) {
2440:                                for (int i = 0, l = nodes.length; i < l; i++) {
2441:                                    ASTNode node = nodes[i];
2442:                                    Integer level = (Integer) nodeSet.matchingNodes
2443:                                            .removeKey(node);
2444:                                    this .patternLocator.matchReportReference(
2445:                                            node, enclosingElement,
2446:                                            method.binding, method.scope, level
2447:                                                    .intValue(), this );
2448:                                }
2449:                                return;
2450:                            }
2451:                        }
2452:                        for (int i = 0, l = nodes.length; i < l; i++)
2453:                            nodeSet.matchingNodes.removeKey(nodes[i]);
2454:                    }
2455:                }
2456:            }
2457:
2458:            /**
2459:             * Report matching in annotations.
2460:             */
2461:            protected void reportMatching(Annotation[] annotations,
2462:                    IJavaElement enclosingElement, Binding elementBinding,
2463:                    MatchingNodeSet nodeSet, boolean matchedContainer,
2464:                    boolean enclosesElement) throws CoreException {
2465:                for (int i = 0, al = annotations.length; i < al; i++) {
2466:                    Annotation annotationType = annotations[i];
2467:
2468:                    // Look for annotation type ref
2469:                    TypeReference typeRef = annotationType.type;
2470:                    Integer level = (Integer) nodeSet.matchingNodes
2471:                            .removeKey(typeRef);
2472:                    if (level != null && matchedContainer) {
2473:                        this .patternLocator.matchReportReference(typeRef,
2474:                                enclosingElement, elementBinding, level
2475:                                        .intValue(), this );
2476:                    }
2477:
2478:                    // Look for attribute ref
2479:                    MemberValuePair[] pairs = annotationType.memberValuePairs();
2480:                    for (int j = 0, pl = pairs.length; j < pl; j++) {
2481:                        MemberValuePair pair = pairs[j];
2482:                        level = (Integer) nodeSet.matchingNodes.removeKey(pair);
2483:                        if (level != null && enclosesElement) {
2484:                            ASTNode reference = (annotationType instanceof  SingleMemberAnnotation) ? (ASTNode) annotationType
2485:                                    : pair;
2486:                            this .patternLocator.matchReportReference(reference,
2487:                                    enclosingElement, pair.binding, level
2488:                                            .intValue(), this );
2489:                        }
2490:                    }
2491:
2492:                    // Look for reference inside annotation
2493:                    ASTNode[] nodes = nodeSet.matchingNodes(
2494:                            annotationType.sourceStart,
2495:                            annotationType.declarationSourceEnd);
2496:                    if (nodes != null) {
2497:                        if (!matchedContainer) {
2498:                            for (int j = 0, nl = nodes.length; j < nl; j++) {
2499:                                nodeSet.matchingNodes.removeKey(nodes[j]);
2500:                            }
2501:                        } else {
2502:                            for (int j = 0, nl = nodes.length; j < nl; j++) {
2503:                                ASTNode node = nodes[j];
2504:                                level = (Integer) nodeSet.matchingNodes
2505:                                        .removeKey(node);
2506:                                if (enclosesElement) {
2507:                                    this .patternLocator.matchReportReference(
2508:                                            node, enclosingElement,
2509:                                            elementBinding, level.intValue(),
2510:                                            this );
2511:                                }
2512:                            }
2513:                        }
2514:                    }
2515:                }
2516:            }
2517:
2518:            /**
2519:             * Visit the given resolved parse tree and report the nodes that match the search pattern.
2520:             */
2521:            protected void reportMatching(CompilationUnitDeclaration unit,
2522:                    boolean mustResolve) throws CoreException {
2523:                MatchingNodeSet nodeSet = this .currentPossibleMatch.nodeSet;
2524:                boolean locatorMustResolve = this .patternLocator.mustResolve;
2525:                if (nodeSet.mustResolve)
2526:                    this .patternLocator.mustResolve = true;
2527:                if (BasicSearchEngine.VERBOSE) {
2528:                    System.out.println("Report matching: "); //$NON-NLS-1$
2529:                    int size = nodeSet.matchingNodes == null ? 0
2530:                            : nodeSet.matchingNodes.elementSize;
2531:                    System.out.print("	- node set: accurate=" + size); //$NON-NLS-1$
2532:                    size = nodeSet.possibleMatchingNodesSet == null ? 0
2533:                            : nodeSet.possibleMatchingNodesSet.elementSize;
2534:                    System.out.println(", possible=" + size); //$NON-NLS-1$
2535:                    System.out.print("	- must resolve: " + mustResolve); //$NON-NLS-1$
2536:                    System.out
2537:                            .print(" (locator: " + this .patternLocator.mustResolve); //$NON-NLS-1$
2538:                    System.out
2539:                            .println(", nodeSet: " + nodeSet.mustResolve + ')'); //$NON-NLS-1$
2540:                }
2541:                if (mustResolve) {
2542:                    this .unitScope = unit.scope.compilationUnitScope();
2543:                    // move the possible matching nodes that exactly match the search pattern to the matching nodes set
2544:                    Object[] nodes = nodeSet.possibleMatchingNodesSet.values;
2545:                    for (int i = 0, l = nodes.length; i < l; i++) {
2546:                        ASTNode node = (ASTNode) nodes[i];
2547:                        if (node == null)
2548:                            continue;
2549:                        if (node instanceof  ImportReference) {
2550:                            // special case for import refs: they don't know their binding
2551:                            // import ref cannot be in the hierarchy of a type
2552:                            if (this .hierarchyResolver != null)
2553:                                continue;
2554:
2555:                            ImportReference importRef = (ImportReference) node;
2556:                            Binding binding = (importRef.bits & ASTNode.OnDemand) != 0 ? unitScope
2557:                                    .getImport(CharOperation.subarray(
2558:                                            importRef.tokens, 0,
2559:                                            importRef.tokens.length), true,
2560:                                            importRef.isStatic())
2561:                                    : unitScope.getImport(importRef.tokens,
2562:                                            false, importRef.isStatic());
2563:                            this .patternLocator.matchLevelAndReportImportRef(
2564:                                    importRef, binding, this );
2565:                        }
2566:                        nodeSet.addMatch(node, this .patternLocator
2567:                                .resolveLevel(node));
2568:                    }
2569:                    nodeSet.possibleMatchingNodesSet = new SimpleSet(3);
2570:                    if (BasicSearchEngine.VERBOSE) {
2571:                        int size = nodeSet.matchingNodes == null ? 0
2572:                                : nodeSet.matchingNodes.elementSize;
2573:                        System.out.print("	- node set: accurate=" + size); //$NON-NLS-1$
2574:                        size = nodeSet.possibleMatchingNodesSet == null ? 0
2575:                                : nodeSet.possibleMatchingNodesSet.elementSize;
2576:                        System.out.println(", possible=" + size); //$NON-NLS-1$
2577:                    }
2578:                } else {
2579:                    this .unitScope = null;
2580:                }
2581:
2582:                if (nodeSet.matchingNodes.elementSize == 0)
2583:                    return; // no matching nodes were found
2584:                this .methodHandles = new HashSet();
2585:
2586:                boolean matchedUnitContainer = (this .matchContainer & PatternLocator.COMPILATION_UNIT_CONTAINER) != 0;
2587:
2588:                // report references in javadoc
2589:                if (unit.javadoc != null) {
2590:                    ASTNode[] nodes = nodeSet.matchingNodes(
2591:                            unit.javadoc.sourceStart, unit.javadoc.sourceEnd);
2592:                    if (nodes != null) {
2593:                        if (!matchedUnitContainer) {
2594:                            for (int i = 0, l = nodes.length; i < l; i++)
2595:                                nodeSet.matchingNodes.removeKey(nodes[i]);
2596:                        } else {
2597:                            IJavaElement element = createPackageDeclarationHandle(unit);
2598:                            for (int i = 0, l = nodes.length; i < l; i++) {
2599:                                ASTNode node = nodes[i];
2600:                                Integer level = (Integer) nodeSet.matchingNodes
2601:                                        .removeKey(node);
2602:                                if (encloses(element))
2603:                                    this .patternLocator.matchReportReference(
2604:                                            node, element, null/*no binding*/,
2605:                                            level.intValue(), this );
2606:                            }
2607:                        }
2608:                    }
2609:                }
2610:
2611:                if (matchedUnitContainer) {
2612:                    ImportReference pkg = unit.currentPackage;
2613:                    if (pkg != null && pkg.annotations != null) {
2614:                        IJavaElement element = createPackageDeclarationHandle(unit);
2615:                        if (element != null) {
2616:                            reportMatching(pkg.annotations, element, null,
2617:                                    nodeSet, true, encloses(element));
2618:                        }
2619:                    }
2620:
2621:                    ImportReference[] imports = unit.imports;
2622:                    if (imports != null) {
2623:                        for (int i = 0, l = imports.length; i < l; i++) {
2624:                            ImportReference importRef = imports[i];
2625:                            Integer level = (Integer) nodeSet.matchingNodes
2626:                                    .removeKey(importRef);
2627:                            if (level != null)
2628:                                this .patternLocator.matchReportImportRef(
2629:                                        importRef, null/*no binding*/,
2630:                                        createImportHandle(importRef), level
2631:                                                .intValue(), this );
2632:                        }
2633:                    }
2634:                }
2635:
2636:                TypeDeclaration[] types = unit.types;
2637:                if (types != null) {
2638:                    for (int i = 0, l = types.length; i < l; i++) {
2639:                        if (nodeSet.matchingNodes.elementSize == 0)
2640:                            return; // reported all the matching nodes
2641:                        TypeDeclaration type = types[i];
2642:                        Integer level = (Integer) nodeSet.matchingNodes
2643:                                .removeKey(type);
2644:                        int accuracy = (level != null && matchedUnitContainer) ? level
2645:                                .intValue()
2646:                                : -1;
2647:                        reportMatching(type, null, accuracy, nodeSet, 1);
2648:                    }
2649:                }
2650:
2651:                // Clear handle cache
2652:                this .methodHandles = null;
2653:                this .bindings.removeKey(this .pattern);
2654:                this .patternLocator.mustResolve = locatorMustResolve;
2655:            }
2656:
2657:            /**
2658:             * Visit the given field declaration and report the nodes that match exactly the
2659:             * search pattern (ie. the ones in the matching nodes set)
2660:             */
2661:            protected void reportMatching(FieldDeclaration field,
2662:                    FieldDeclaration[] otherFields, TypeDeclaration type,
2663:                    IJavaElement parent, int accuracy, boolean typeInHierarchy,
2664:                    MatchingNodeSet nodeSet) throws CoreException {
2665:                IJavaElement enclosingElement = null;
2666:                if (accuracy > -1) {
2667:                    enclosingElement = createHandle(field, type, parent);
2668:                    if (encloses(enclosingElement)) {
2669:                        int offset = field.sourceStart;
2670:                        SearchMatch match = newDeclarationMatch(
2671:                                enclosingElement, field.binding, accuracy,
2672:                                offset, field.sourceEnd - offset + 1);
2673:                        if (field.initialization instanceof  AllocationExpression) {
2674:                            reportAccurateEnumConstructorReference(match,
2675:                                    field,
2676:                                    (AllocationExpression) field.initialization);
2677:                        } else {
2678:                            report(match);
2679:                        }
2680:                    }
2681:                }
2682:
2683:                // handle the nodes for the local type first
2684:                if ((field.bits & ASTNode.HasLocalType) != 0) {
2685:                    if (enclosingElement == null)
2686:                        enclosingElement = createHandle(field, type, parent);
2687:                    LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor(
2688:                            enclosingElement, field.binding, nodeSet);
2689:                    try {
2690:                        field.traverse(localDeclarationVisitor, null);
2691:                    } catch (WrappedCoreException e) {
2692:                        throw e.coreException;
2693:                    }
2694:                }
2695:
2696:                // report annotations
2697:                if (field.annotations != null) {
2698:                    if (enclosingElement == null) {
2699:                        enclosingElement = createHandle(field, type, parent);
2700:                    }
2701:                    reportMatching(field.annotations, enclosingElement,
2702:                            field.binding, nodeSet, true, true);
2703:                }
2704:
2705:                if (typeInHierarchy) {
2706:                    // Look at field declaration
2707:                    if (field.endPart1Position != 0) { // not necessary if field is an initializer
2708:                        ASTNode[] nodes = nodeSet.matchingNodes(
2709:                                field.declarationSourceStart,
2710:                                field.endPart1Position);
2711:                        if (nodes != null) {
2712:                            if ((this .matchContainer & PatternLocator.FIELD_CONTAINER) == 0) {
2713:                                for (int i = 0, l = nodes.length; i < l; i++)
2714:                                    nodeSet.matchingNodes.removeKey(nodes[i]);
2715:                            } else {
2716:                                if (enclosingElement == null)
2717:                                    enclosingElement = createHandle(field,
2718:                                            type, parent);
2719:                                if (encloses(enclosingElement)) {
2720:                                    for (int i = 0, l = nodes.length; i < l; i++) {
2721:                                        ASTNode node = nodes[i];
2722:                                        Integer level = (Integer) nodeSet.matchingNodes
2723:                                                .removeKey(node);
2724:                                        IJavaElement[] otherElements = null;
2725:                                        if (otherFields != null) {
2726:                                            int length = otherFields.length;
2727:                                            int size = 0;
2728:                                            while (size < length
2729:                                                    && otherFields[size] != null) {
2730:                                                size++;
2731:                                            }
2732:                                            otherElements = new IJavaElement[size];
2733:                                            for (int j = 0; j < size; j++) {
2734:                                                otherElements[j] = createHandle(
2735:                                                        otherFields[j], type,
2736:                                                        parent);
2737:                                            }
2738:                                        }
2739:                                        this .patternLocator
2740:                                                .matchReportReference(node,
2741:                                                        enclosingElement, null,
2742:                                                        otherElements,
2743:                                                        field.binding, level
2744:                                                                .intValue(),
2745:                                                        this );
2746:                                    }
2747:                                }
2748:                            }
2749:                        }
2750:                    }
2751:
2752:                    // Look in initializer
2753:                    int fieldEnd = field.endPart2Position == 0 ? field.declarationSourceEnd
2754:                            : field.endPart2Position;
2755:                    ASTNode[] nodes = nodeSet.matchingNodes(field.sourceStart,
2756:                            fieldEnd);
2757:                    if (nodes != null) {
2758:                        if ((this .matchContainer & PatternLocator.FIELD_CONTAINER) == 0) {
2759:                            for (int i = 0, l = nodes.length; i < l; i++)
2760:                                nodeSet.matchingNodes.removeKey(nodes[i]);
2761:                        } else {
2762:                            if (enclosingElement == null) {
2763:                                enclosingElement = createHandle(field, type,
2764:                                        parent);
2765:                            }
2766:                            if (encloses(enclosingElement)) {
2767:                                for (int i = 0, l = nodes.length; i < l; i++) {
2768:                                    ASTNode node = nodes[i];
2769:                                    Integer level = (Integer) nodeSet.matchingNodes
2770:                                            .removeKey(node);
2771:                                    if (node instanceof  TypeDeclaration) {
2772:                                        // use field declaration to report match (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=88174)
2773:                                        AllocationExpression allocation = ((TypeDeclaration) node).allocation;
2774:                                        if (allocation != null
2775:                                                && allocation.enumConstant != null) {
2776:                                            node = field;
2777:                                        }
2778:                                    }
2779:                                    // Set block scope for initializer in case there would have other local and other elements to report
2780:                                    BlockScope blockScope = null;
2781:                                    if (field.getKind() == AbstractVariableDeclaration.INITIALIZER) {
2782:                                        Block block = ((Initializer) field).block;
2783:                                        if (block != null)
2784:                                            blockScope = block.scope;
2785:                                    }
2786:                                    this .patternLocator.matchReportReference(
2787:                                            node, enclosingElement,
2788:                                            field.binding, blockScope, level
2789:                                                    .intValue(), this );
2790:                                }
2791:                            }
2792:                        }
2793:                    }
2794:                }
2795:            }
2796:
2797:            /**
2798:             * Visit the given type declaration and report the nodes that match exactly the
2799:             * search pattern (ie. the ones in the matching nodes set)
2800:             */
2801:            protected void reportMatching(TypeDeclaration type,
2802:                    IJavaElement parent, int accuracy, MatchingNodeSet nodeSet,
2803:                    int occurrenceCount) throws CoreException {
2804:                // create type handle
2805:                IJavaElement enclosingElement = parent;
2806:                if (enclosingElement == null) {
2807:                    enclosingElement = createTypeHandle(new String(type.name));
2808:                } else if (enclosingElement instanceof  IType) {
2809:                    enclosingElement = ((IType) parent).getType(new String(
2810:                            type.name));
2811:                } else if (enclosingElement instanceof  IMember) {
2812:                    IMember member = (IMember) parent;
2813:                    if (member.isBinary()) {
2814:                        enclosingElement = ((IClassFile) this .currentPossibleMatch.openable)
2815:                                .getType();
2816:                    } else {
2817:                        enclosingElement = member.getType(
2818:                                new String(type.name), occurrenceCount);
2819:                    }
2820:                }
2821:                if (enclosingElement == null)
2822:                    return;
2823:                boolean enclosesElement = encloses(enclosingElement);
2824:
2825:                // report the type declaration
2826:                if (accuracy > -1 && enclosesElement) {
2827:                    int offset = type.sourceStart;
2828:                    SearchMatch match = this .patternLocator
2829:                            .newDeclarationMatch(type, enclosingElement,
2830:                                    type.binding, accuracy, type.sourceEnd
2831:                                            - offset + 1, this );
2832:                    report(match);
2833:                }
2834:
2835:                boolean matchedClassContainer = (this .matchContainer & PatternLocator.CLASS_CONTAINER) != 0;
2836:
2837:                // report the type parameters
2838:                if (type.typeParameters != null) {
2839:                    reportMatching(type.typeParameters, enclosingElement,
2840:                            parent, type.binding, nodeSet);
2841:                }
2842:
2843:                // report annotations
2844:                if (type.annotations != null) {
2845:                    reportMatching(type.annotations, enclosingElement,
2846:                            type.binding, nodeSet, matchedClassContainer,
2847:                            enclosesElement);
2848:                }
2849:
2850:                // report references in javadoc
2851:                if (type.javadoc != null) {
2852:                    ASTNode[] nodes = nodeSet.matchingNodes(
2853:                            type.declarationSourceStart, type.sourceStart);
2854:                    if (nodes != null) {
2855:                        if (!matchedClassContainer) {
2856:                            for (int i = 0, l = nodes.length; i < l; i++)
2857:                                nodeSet.matchingNodes.removeKey(nodes[i]);
2858:                        } else {
2859:                            for (int i = 0, l = nodes.length; i < l; i++) {
2860:                                ASTNode node = nodes[i];
2861:                                Integer level = (Integer) nodeSet.matchingNodes
2862:                                        .removeKey(node);
2863:                                if (enclosesElement) {
2864:                                    this .patternLocator.matchReportReference(
2865:                                            node, enclosingElement,
2866:                                            type.binding, level.intValue(),
2867:                                            this );
2868:                                }
2869:                            }
2870:                        }
2871:                    }
2872:                }
2873:
2874:                // super types
2875:                if ((type.bits & ASTNode.IsAnonymousType) != 0) {
2876:                    TypeReference super Type = type.allocation.type;
2877:                    if (super Type != null) {
2878:                        Integer level = (Integer) nodeSet.matchingNodes
2879:                                .removeKey(super Type);
2880:                        if (level != null && matchedClassContainer)
2881:                            this .patternLocator.matchReportReference(super Type,
2882:                                    enclosingElement, type.binding, level
2883:                                            .intValue(), this );
2884:                    }
2885:                } else {
2886:                    TypeReference super Class = type.super class;
2887:                    if (super Class != null) {
2888:                        reportMatchingSuper(super Class, enclosingElement,
2889:                                type.binding, nodeSet, matchedClassContainer);
2890:                    }
2891:                    TypeReference[] super Interfaces = type.super Interfaces;
2892:                    if (super Interfaces != null) {
2893:                        for (int i = 0, l = super Interfaces.length; i < l; i++) {
2894:                            reportMatchingSuper(super Interfaces[i],
2895:                                    enclosingElement, type.binding, nodeSet,
2896:                                    matchedClassContainer);
2897:                        }
2898:                    }
2899:                }
2900:
2901:                // filter out element not in hierarchy scope
2902:                boolean typeInHierarchy = type.binding == null
2903:                        || typeInHierarchy(type.binding);
2904:                matchedClassContainer = matchedClassContainer
2905:                        && typeInHierarchy;
2906:
2907:                // Visit fields
2908:                FieldDeclaration[] fields = type.fields;
2909:                if (fields != null) {
2910:                    if (nodeSet.matchingNodes.elementSize == 0)
2911:                        return; // end as all matching nodes were reported
2912:                    FieldDeclaration[] otherFields = null;
2913:                    int first = -1;
2914:                    int length = fields.length;
2915:                    for (int i = 0; i < length; i++) {
2916:                        FieldDeclaration field = fields[i];
2917:                        boolean last = field.endPart2Position == 0
2918:                                || field.declarationEnd == field.endPart2Position;
2919:                        // Store first index of multiple field declaration
2920:                        if (!last) {
2921:                            if (first == -1) {
2922:                                first = i;
2923:                            }
2924:                        }
2925:                        if (first >= 0) {
2926:                            // Store all multiple fields but first one for other elements
2927:                            if (i > first) {
2928:                                if (otherFields == null) {
2929:                                    otherFields = new FieldDeclaration[length
2930:                                            - i];
2931:                                }
2932:                                otherFields[i - 1 - first] = field;
2933:                            }
2934:                            // On last field, report match with all other elements
2935:                            if (last) {
2936:                                for (int j = first; j <= i; j++) {
2937:                                    Integer level = (Integer) nodeSet.matchingNodes
2938:                                            .removeKey(fields[j]);
2939:                                    int value = (level != null && matchedClassContainer) ? level
2940:                                            .intValue()
2941:                                            : -1;
2942:                                    reportMatching(fields[j], otherFields,
2943:                                            type, enclosingElement, value,
2944:                                            typeInHierarchy, nodeSet);
2945:                                }
2946:                                first = -1;
2947:                                otherFields = null;
2948:                            }
2949:                        } else {
2950:                            // Single field, report normally
2951:                            Integer level = (Integer) nodeSet.matchingNodes
2952:                                    .removeKey(field);
2953:                            int value = (level != null && matchedClassContainer) ? level
2954:                                    .intValue()
2955:                                    : -1;
2956:                            reportMatching(field, null, type, enclosingElement,
2957:                                    value, typeInHierarchy, nodeSet);
2958:                        }
2959:                    }
2960:                }
2961:
2962:                // Visit methods
2963:                AbstractMethodDeclaration[] methods = type.methods;
2964:                if (methods != null) {
2965:                    if (nodeSet.matchingNodes.elementSize == 0)
2966:                        return; // end as all matching nodes were reported
2967:                    for (int i = 0, l = methods.length; i < l; i++) {
2968:                        AbstractMethodDeclaration method = methods[i];
2969:                        Integer level = (Integer) nodeSet.matchingNodes
2970:                                .removeKey(method);
2971:                        int value = (level != null && matchedClassContainer) ? level
2972:                                .intValue()
2973:                                : -1;
2974:                        reportMatching(type, method, enclosingElement, value,
2975:                                typeInHierarchy, nodeSet);
2976:                    }
2977:                }
2978:
2979:                // Visit types
2980:                TypeDeclaration[] memberTypes = type.memberTypes;
2981:                if (memberTypes != null) {
2982:                    for (int i = 0, l = memberTypes.length; i < l; i++) {
2983:                        if (nodeSet.matchingNodes.elementSize == 0)
2984:                            return; // end as all matching nodes were reported
2985:                        TypeDeclaration memberType = memberTypes[i];
2986:                        Integer level = (Integer) nodeSet.matchingNodes
2987:                                .removeKey(memberType);
2988:                        int value = (level != null && matchedClassContainer) ? level
2989:                                .intValue()
2990:                                : -1;
2991:                        reportMatching(memberType, enclosingElement, value,
2992:                                nodeSet, 1);
2993:                    }
2994:                }
2995:            }
2996:
2997:            /**
2998:             * Report matches in type parameters.
2999:             */
3000:            protected void reportMatching(TypeParameter[] typeParameters,
3001:                    IJavaElement enclosingElement, IJavaElement parent,
3002:                    Binding binding, MatchingNodeSet nodeSet)
3003:                    throws CoreException {
3004:                if (typeParameters == null)
3005:                    return;
3006:                for (int i = 0, l = typeParameters.length; i < l; i++) {
3007:                    TypeParameter typeParameter = typeParameters[i];
3008:                    if (typeParameter != null) {
3009:                        Integer level = (Integer) nodeSet.matchingNodes
3010:                                .removeKey(typeParameter);
3011:                        if (level != null) {
3012:                            if (level.intValue() > -1
3013:                                    && encloses(enclosingElement)) {
3014:                                int offset = typeParameter.sourceStart;
3015:                                SearchMatch match = this .patternLocator
3016:                                        .newDeclarationMatch(typeParameter,
3017:                                                enclosingElement, binding,
3018:                                                level.intValue(),
3019:                                                typeParameter.sourceEnd
3020:                                                        - offset + 1, this );
3021:                                report(match);
3022:                            }
3023:                        }
3024:                        if (typeParameter.type != null) {
3025:                            level = (Integer) nodeSet.matchingNodes
3026:                                    .removeKey(typeParameter.type);
3027:                            if (level != null) {
3028:                                IJavaElement localElement = createHandle(
3029:                                        typeParameter, enclosingElement);
3030:                                this .patternLocator.matchReportReference(
3031:                                        typeParameter.type, enclosingElement,
3032:                                        localElement, null, binding, level
3033:                                                .intValue(), this );
3034:                            }
3035:                        }
3036:                        if (typeParameter.bounds != null) {
3037:                            for (int j = 0, b = typeParameter.bounds.length; j < b; j++) {
3038:                                level = (Integer) nodeSet.matchingNodes
3039:                                        .removeKey(typeParameter.bounds[j]);
3040:                                if (level != null) {
3041:                                    IJavaElement localElement = createHandle(
3042:                                            typeParameter, enclosingElement);
3043:                                    this .patternLocator.matchReportReference(
3044:                                            typeParameter.bounds[j],
3045:                                            enclosingElement, localElement,
3046:                                            null, binding, level.intValue(),
3047:                                            this );
3048:                                }
3049:                            }
3050:                        }
3051:                    }
3052:                }
3053:            }
3054:
3055:            protected void reportMatchingSuper(TypeReference super Reference,
3056:                    IJavaElement enclosingElement, Binding elementBinding,
3057:                    MatchingNodeSet nodeSet, boolean matchedClassContainer)
3058:                    throws CoreException {
3059:                ASTNode[] nodes = null;
3060:                if (super Reference instanceof  ParameterizedSingleTypeReference
3061:                        || super Reference instanceof  ParameterizedQualifiedTypeReference) {
3062:                    long lastTypeArgumentInfo = findLastTypeArgumentInfo(super Reference);
3063:                    nodes = nodeSet.matchingNodes(super Reference.sourceStart,
3064:                            (int) lastTypeArgumentInfo);
3065:                }
3066:                if (nodes != null) {
3067:                    if ((this .matchContainer & PatternLocator.CLASS_CONTAINER) == 0) {
3068:                        for (int i = 0, l = nodes.length; i < l; i++)
3069:                            nodeSet.matchingNodes.removeKey(nodes[i]);
3070:                    } else {
3071:                        if (encloses(enclosingElement))
3072:                            for (int i = 0, l = nodes.length; i < l; i++) {
3073:                                ASTNode node = nodes[i];
3074:                                Integer level = (Integer) nodeSet.matchingNodes
3075:                                        .removeKey(node);
3076:                                this .patternLocator.matchReportReference(node,
3077:                                        enclosingElement, elementBinding, level
3078:                                                .intValue(), this );
3079:                            }
3080:                    }
3081:                } else {
3082:                    Integer level = (Integer) nodeSet.matchingNodes
3083:                            .removeKey(super Reference);
3084:                    if (level != null && matchedClassContainer)
3085:                        this .patternLocator.matchReportReference(
3086:                                super Reference, enclosingElement,
3087:                                elementBinding, level.intValue(), this );
3088:                }
3089:            }
3090:
3091:            protected boolean typeInHierarchy(ReferenceBinding binding) {
3092:                if (this .hierarchyResolver == null)
3093:                    return true; // not a hierarchy scope
3094:                if (this .hierarchyResolver.subOrSuperOfFocus(binding))
3095:                    return true;
3096:
3097:                if (this .allSuperTypeNames != null) {
3098:                    char[][] compoundName = binding.compoundName;
3099:                    for (int i = 0, length = this .allSuperTypeNames.length; i < length; i++)
3100:                        if (CharOperation.equals(compoundName,
3101:                                this .allSuperTypeNames[i]))
3102:                            return true;
3103:                }
3104:                return false;
3105:            }
3106:        }
ww_w___.___j__a__v___a2___s___._c___o___m__ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.