Source Code Cross Referenced for SourceMapper.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » core » 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 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2006 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;
0011:
0012:        import java.io.File;
0013:        import java.io.FilenameFilter;
0014:        import java.io.IOException;
0015:        import java.util.ArrayList;
0016:        import java.util.Collections;
0017:        import java.util.Comparator;
0018:        import java.util.Enumeration;
0019:        import java.util.HashMap;
0020:        import java.util.HashSet;
0021:        import java.util.Iterator;
0022:        import java.util.Map;
0023:        import java.util.Set;
0024:        import java.util.zip.ZipEntry;
0025:        import java.util.zip.ZipFile;
0026:
0027:        import org.eclipse.core.resources.IContainer;
0028:        import org.eclipse.core.resources.IFile;
0029:        import org.eclipse.core.resources.IFolder;
0030:        import org.eclipse.core.resources.IResource;
0031:        import org.eclipse.core.resources.ResourcesPlugin;
0032:        import org.eclipse.core.runtime.CoreException;
0033:        import org.eclipse.core.runtime.IPath;
0034:        import org.eclipse.core.runtime.IStatus;
0035:        import org.eclipse.core.runtime.Path;
0036:        import org.eclipse.jdt.core.Flags;
0037:        import org.eclipse.jdt.core.IClassFile;
0038:        import org.eclipse.jdt.core.IField;
0039:        import org.eclipse.jdt.core.IJavaElement;
0040:        import org.eclipse.jdt.core.IJavaProject;
0041:        import org.eclipse.jdt.core.IMember;
0042:        import org.eclipse.jdt.core.IMethod;
0043:        import org.eclipse.jdt.core.IPackageFragmentRoot;
0044:        import org.eclipse.jdt.core.ISourceRange;
0045:        import org.eclipse.jdt.core.IType;
0046:        import org.eclipse.jdt.core.ITypeParameter;
0047:        import org.eclipse.jdt.core.JavaConventions;
0048:        import org.eclipse.jdt.core.JavaCore;
0049:        import org.eclipse.jdt.core.JavaModelException;
0050:        import org.eclipse.jdt.core.Signature;
0051:        import org.eclipse.jdt.core.compiler.CategorizedProblem;
0052:        import org.eclipse.jdt.core.compiler.CharOperation;
0053:        import org.eclipse.jdt.internal.compiler.IProblemFactory;
0054:        import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
0055:        import org.eclipse.jdt.internal.compiler.SourceElementParser;
0056:        import org.eclipse.jdt.internal.compiler.env.IBinaryType;
0057:        import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
0058:        import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
0059:        import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
0060:        import org.eclipse.jdt.internal.compiler.util.Util;
0061:        import org.eclipse.jdt.internal.core.util.ReferenceInfoAdapter;
0062:
0063:        /**
0064:         * A SourceMapper maps source code in a ZIP file to binary types in
0065:         * a JAR. The SourceMapper uses the fuzzy parser to identify source
0066:         * fragments in a .java file, and attempts to match the source code
0067:         * with children in a binary type. A SourceMapper is associated
0068:         * with a JarPackageFragment by an AttachSourceOperation.
0069:         *
0070:         * @see org.eclipse.jdt.internal.core.JarPackageFragment
0071:         */
0072:        public class SourceMapper extends ReferenceInfoAdapter implements 
0073:                ISourceElementRequestor, SuffixConstants {
0074:
0075:            public static boolean VERBOSE = false;
0076:            /**
0077:             * Specifies the file name filter use to compute the root paths.
0078:             */
0079:            private static final FilenameFilter FILENAME_FILTER = new FilenameFilter() {
0080:                public boolean accept(File dir, String name) {
0081:                    return org.eclipse.jdt.internal.core.util.Util
0082:                            .isJavaLikeFileName(name);
0083:                }
0084:            };
0085:            /**
0086:             * Specifies the location of the package fragment roots within
0087:             * the zip (empty specifies the default root). <code>null</code> is
0088:             * not a valid root path.
0089:             */
0090:            protected ArrayList rootPaths;
0091:
0092:            /**
0093:             * The binary type source is being mapped for
0094:             */
0095:            protected BinaryType binaryType;
0096:
0097:            /**
0098:             * The location of the zip file containing source.
0099:             */
0100:            protected IPath sourcePath;
0101:            /**
0102:             * Specifies the location of the package fragment root within
0103:             * the zip (empty specifies the default root). <code>null</code> is
0104:             * not a valid root path.
0105:             */
0106:            protected String rootPath = ""; //$NON-NLS-1$
0107:
0108:            /**
0109:             * Table that maps a binary method to its parameter names.
0110:             * Keys are the method handles, entries are <code>char[][]</code>.
0111:             */
0112:            protected HashMap parameterNames;
0113:
0114:            /**
0115:             * Table that maps a binary element to its <code>SourceRange</code>s.
0116:             * Keys are the element handles, entries are <code>SourceRange[]</code> which
0117:             * is a two element array; the first being source range, the second
0118:             * being name range.
0119:             */
0120:            protected HashMap sourceRanges;
0121:
0122:            /*
0123:             * A map from IJavaElement to String[]
0124:             */
0125:            protected HashMap categories;
0126:
0127:            /**
0128:             * The unknown source range {-1, 0}
0129:             */
0130:            public static final SourceRange UNKNOWN_RANGE = new SourceRange(-1,
0131:                    0);
0132:
0133:            /**
0134:             * The position within the source of the start of the
0135:             * current member element, or -1 if we are outside a member.
0136:             */
0137:            protected int[] memberDeclarationStart;
0138:            /**
0139:             * The <code>SourceRange</code> of the name of the current member element.
0140:             */
0141:            protected SourceRange[] memberNameRange;
0142:            /**
0143:             * The name of the current member element.
0144:             */
0145:            protected String[] memberName;
0146:
0147:            /**
0148:             * The parameter names for the current member method element.
0149:             */
0150:            protected char[][][] methodParameterNames;
0151:
0152:            /**
0153:             * The parameter types for the current member method element.
0154:             */
0155:            protected char[][][] methodParameterTypes;
0156:
0157:            /**
0158:             * The element searched for
0159:             */
0160:            protected IJavaElement searchedElement;
0161:
0162:            /**
0163:             * imports references
0164:             */
0165:            private HashMap importsTable;
0166:            private HashMap importsCounterTable;
0167:
0168:            /**
0169:             * Enclosing type information
0170:             */
0171:            IType[] types;
0172:            int[] typeDeclarationStarts;
0173:            SourceRange[] typeNameRanges;
0174:            int[] typeModifiers;
0175:            int typeDepth;
0176:
0177:            /**
0178:             *  Anonymous counter in case we want to map the source of an anonymous class.
0179:             */
0180:            int anonymousCounter;
0181:            int anonymousClassName;
0182:
0183:            /**
0184:             *Options to be used
0185:             */
0186:            String encoding;
0187:            Map options;
0188:
0189:            /**
0190:             * Use to handle root paths inference
0191:             */
0192:            private boolean areRootPathsComputed;
0193:
0194:            public SourceMapper() {
0195:                this .areRootPathsComputed = false;
0196:            }
0197:
0198:            /**
0199:             * Creates a <code>SourceMapper</code> that locates source in the zip file
0200:             * at the given location in the specified package fragment root.
0201:             */
0202:            public SourceMapper(IPath sourcePath, String rootPath, Map options) {
0203:                this .areRootPathsComputed = false;
0204:                this .options = options;
0205:                try {
0206:                    this .encoding = ResourcesPlugin.getWorkspace().getRoot()
0207:                            .getDefaultCharset();
0208:                } catch (CoreException e) {
0209:                    // use no encoding
0210:                }
0211:                if (rootPath != null) {
0212:                    this .rootPaths = new ArrayList();
0213:                    this .rootPaths.add(rootPath);
0214:                }
0215:                this .sourcePath = sourcePath;
0216:                this .sourceRanges = new HashMap();
0217:                this .parameterNames = new HashMap();
0218:                this .importsTable = new HashMap();
0219:                this .importsCounterTable = new HashMap();
0220:            }
0221:
0222:            /**
0223:             * @see ISourceElementRequestor
0224:             */
0225:            public void acceptImport(int declarationStart, int declarationEnd,
0226:                    char[][] tokens, boolean onDemand, int modifiers) {
0227:                char[][] imports = (char[][]) this .importsTable
0228:                        .get(this .binaryType);
0229:                int importsCounter;
0230:                if (imports == null) {
0231:                    imports = new char[5][];
0232:                    importsCounter = 0;
0233:                } else {
0234:                    importsCounter = ((Integer) this .importsCounterTable
0235:                            .get(this .binaryType)).intValue();
0236:                }
0237:                if (imports.length == importsCounter) {
0238:                    System.arraycopy(imports, 0,
0239:                            (imports = new char[importsCounter * 2][]), 0,
0240:                            importsCounter);
0241:                }
0242:                char[] name = CharOperation.concatWith(tokens, '.');
0243:                if (onDemand) {
0244:                    int nameLength = name.length;
0245:                    System.arraycopy(name, 0,
0246:                            (name = new char[nameLength + 2]), 0, nameLength);
0247:                    name[nameLength] = '.';
0248:                    name[nameLength + 1] = '*';
0249:                }
0250:                imports[importsCounter++] = name;
0251:                this .importsTable.put(this .binaryType, imports);
0252:                this .importsCounterTable.put(this .binaryType, new Integer(
0253:                        importsCounter));
0254:            }
0255:
0256:            /**
0257:             * @see ISourceElementRequestor
0258:             */
0259:            public void acceptLineSeparatorPositions(int[] positions) {
0260:                //do nothing
0261:            }
0262:
0263:            /**
0264:             * @see ISourceElementRequestor
0265:             */
0266:            public void acceptPackage(int declarationStart, int declarationEnd,
0267:                    char[] name) {
0268:                //do nothing
0269:            }
0270:
0271:            /**
0272:             * @see ISourceElementRequestor
0273:             */
0274:            public void acceptProblem(CategorizedProblem problem) {
0275:                //do nothing
0276:            }
0277:
0278:            private void addCategories(IJavaElement element,
0279:                    char[][] elementCategories) {
0280:                if (elementCategories == null)
0281:                    return;
0282:                if (this .categories == null)
0283:                    this .categories = new HashMap();
0284:                this .categories.put(element, CharOperation
0285:                        .toStrings(elementCategories));
0286:            }
0287:
0288:            /**
0289:             * Closes this <code>SourceMapper</code>'s zip file. Once this is done, this
0290:             * <code>SourceMapper</code> cannot be used again.
0291:             */
0292:            public void close() {
0293:                this .sourceRanges = null;
0294:                this .parameterNames = null;
0295:            }
0296:
0297:            /**
0298:             * Converts these type names to unqualified signatures. This needs to be done in order to be consistent
0299:             * with the way the source range is retrieved.
0300:             * @see SourceMapper#getUnqualifiedMethodHandle
0301:             * @see Signature
0302:             */
0303:            private String[] convertTypeNamesToSigs(char[][] typeNames) {
0304:                if (typeNames == null)
0305:                    return CharOperation.NO_STRINGS;
0306:                int n = typeNames.length;
0307:                if (n == 0)
0308:                    return CharOperation.NO_STRINGS;
0309:                String[] typeSigs = new String[n];
0310:                for (int i = 0; i < n; ++i) {
0311:                    char[] typeSig = Signature.createCharArrayTypeSignature(
0312:                            typeNames[i], false);
0313:
0314:                    // transforms signatures that contains a qualification into unqualified signatures
0315:                    // e.g. "QX<+QMap.Entry;>;" becomes "QX<+QEntry;>;"
0316:                    StringBuffer simpleTypeSig = null;
0317:                    int start = 0;
0318:                    int dot = -1;
0319:                    int length = typeSig.length;
0320:                    for (int j = 0; j < length; j++) {
0321:                        switch (typeSig[j]) {
0322:                        case Signature.C_UNRESOLVED:
0323:                            if (simpleTypeSig != null)
0324:                                simpleTypeSig.append(typeSig, start, j - start);
0325:                            start = j;
0326:                            break;
0327:                        case Signature.C_DOT:
0328:                            dot = j;
0329:                            break;
0330:                        case Signature.C_GENERIC_START:
0331:                        case Signature.C_NAME_END:
0332:                            if (dot > start) {
0333:                                if (simpleTypeSig == null)
0334:                                    simpleTypeSig = new StringBuffer().append(
0335:                                            typeSig, 0, start);
0336:                                simpleTypeSig.append(Signature.C_UNRESOLVED);
0337:                                simpleTypeSig.append(typeSig, dot + 1, j - dot
0338:                                        - 1);
0339:                                start = j;
0340:                            }
0341:                            break;
0342:                        }
0343:                    }
0344:                    if (simpleTypeSig == null) {
0345:                        typeSigs[i] = new String(typeSig);
0346:                    } else {
0347:                        simpleTypeSig.append(typeSig, start, length - start);
0348:                        typeSigs[i] = simpleTypeSig.toString();
0349:                    }
0350:                }
0351:                return typeSigs;
0352:            }
0353:
0354:            private synchronized void computeAllRootPaths(IType type) {
0355:                if (this .areRootPathsComputed) {
0356:                    return;
0357:                }
0358:                IPackageFragmentRoot root = (IPackageFragmentRoot) type
0359:                        .getPackageFragment().getParent();
0360:                final HashSet tempRoots = new HashSet();
0361:                long time = 0;
0362:                if (VERBOSE) {
0363:                    System.out
0364:                            .println("compute all root paths for " + root.getElementName()); //$NON-NLS-1$
0365:                    time = System.currentTimeMillis();
0366:                }
0367:                final HashSet firstLevelPackageNames = new HashSet();
0368:                boolean containsADefaultPackage = false;
0369:
0370:                if (root.isArchive()) {
0371:                    JarPackageFragmentRoot jarPackageFragmentRoot = (JarPackageFragmentRoot) root;
0372:                    IJavaProject project = jarPackageFragmentRoot
0373:                            .getJavaProject();
0374:                    String sourceLevel = null;
0375:                    String complianceLevel = null;
0376:                    JavaModelManager manager = JavaModelManager
0377:                            .getJavaModelManager();
0378:                    ZipFile zip = null;
0379:                    try {
0380:                        zip = manager.getZipFile(jarPackageFragmentRoot
0381:                                .getPath());
0382:                        for (Enumeration entries = zip.entries(); entries
0383:                                .hasMoreElements();) {
0384:                            ZipEntry entry = (ZipEntry) entries.nextElement();
0385:                            String entryName = entry.getName();
0386:                            if (!entry.isDirectory()) {
0387:                                int index = entryName.indexOf('/');
0388:                                if (index != -1
0389:                                        && Util.isClassFileName(entryName)) {
0390:                                    String firstLevelPackageName = entryName
0391:                                            .substring(0, index);
0392:                                    if (!firstLevelPackageNames
0393:                                            .contains(firstLevelPackageName)) {
0394:                                        if (sourceLevel == null) {
0395:                                            sourceLevel = project.getOption(
0396:                                                    JavaCore.COMPILER_SOURCE,
0397:                                                    true);
0398:                                            complianceLevel = project
0399:                                                    .getOption(
0400:                                                            JavaCore.COMPILER_COMPLIANCE,
0401:                                                            true);
0402:                                        }
0403:                                        IStatus status = JavaConventions
0404:                                                .validatePackageName(
0405:                                                        firstLevelPackageName,
0406:                                                        sourceLevel,
0407:                                                        complianceLevel);
0408:                                        if (status.isOK()
0409:                                                || status.getSeverity() == IStatus.WARNING) {
0410:                                            firstLevelPackageNames
0411:                                                    .add(firstLevelPackageName);
0412:                                        }
0413:                                    }
0414:                                } else if (Util.isClassFileName(entryName)) {
0415:                                    containsADefaultPackage = true;
0416:                                }
0417:                            }
0418:                        }
0419:                    } catch (CoreException e) {
0420:                        // ignore
0421:                    } finally {
0422:                        manager.closeZipFile(zip); // handle null case
0423:                    }
0424:                } else {
0425:                    Object target = JavaModel.getTarget(ResourcesPlugin
0426:                            .getWorkspace().getRoot(), root.getPath(), true);
0427:                    if (target instanceof  IResource) {
0428:                        IResource resource = (IResource) target;
0429:                        if (resource instanceof  IContainer) {
0430:                            try {
0431:                                IResource[] members = ((IContainer) resource)
0432:                                        .members();
0433:                                for (int i = 0, max = members.length; i < max; i++) {
0434:                                    IResource member = members[i];
0435:                                    if (member.getType() == IResource.FOLDER) {
0436:                                        firstLevelPackageNames.add(member
0437:                                                .getName());
0438:                                    } else if (Util.isClassFileName(member
0439:                                            .getName())) {
0440:                                        containsADefaultPackage = true;
0441:                                    }
0442:                                }
0443:                            } catch (CoreException e) {
0444:                                // ignore
0445:                            }
0446:                        }
0447:                    } else if (target instanceof  File) {
0448:                        File file = (File) target;
0449:                        if (file.isDirectory()) {
0450:                            File[] files = file.listFiles();
0451:                            for (int i = 0, max = files.length; i < max; i++) {
0452:                                File currentFile = files[i];
0453:                                if (currentFile.isDirectory()) {
0454:                                    firstLevelPackageNames.add(currentFile
0455:                                            .getName());
0456:                                } else if (Util.isClassFileName(currentFile
0457:                                        .getName())) {
0458:                                    containsADefaultPackage = true;
0459:                                }
0460:                            }
0461:                        }
0462:                    }
0463:                }
0464:
0465:                if (Util.isArchiveFileName(this .sourcePath.lastSegment())) {
0466:                    JavaModelManager manager = JavaModelManager
0467:                            .getJavaModelManager();
0468:                    ZipFile zip = null;
0469:                    try {
0470:                        zip = manager.getZipFile(this .sourcePath);
0471:                        for (Enumeration entries = zip.entries(); entries
0472:                                .hasMoreElements();) {
0473:                            ZipEntry entry = (ZipEntry) entries.nextElement();
0474:                            String entryName;
0475:                            if (!entry.isDirectory()
0476:                                    && org.eclipse.jdt.internal.core.util.Util
0477:                                            .isJavaLikeFileName(entryName = entry
0478:                                                    .getName())) {
0479:                                IPath path = new Path(entryName);
0480:                                int segmentCount = path.segmentCount();
0481:                                if (segmentCount > 1) {
0482:                                    for (int i = 0, max = path.segmentCount() - 1; i < max; i++) {
0483:                                        if (firstLevelPackageNames
0484:                                                .contains(path.segment(i))) {
0485:                                            tempRoots.add(path.uptoSegment(i));
0486:                                            // don't break here as this path could contain other first level package names (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=74014)
0487:                                        }
0488:                                        if (i == max - 1
0489:                                                && containsADefaultPackage) {
0490:                                            tempRoots
0491:                                                    .add(path.uptoSegment(max));
0492:                                        }
0493:                                    }
0494:                                } else if (containsADefaultPackage) {
0495:                                    tempRoots.add(new Path("")); //$NON-NLS-1$
0496:                                }
0497:                            }
0498:                        }
0499:                    } catch (CoreException e) {
0500:                        // ignore
0501:                    } finally {
0502:                        manager.closeZipFile(zip); // handle null case
0503:                    }
0504:                } else {
0505:                    Object target = JavaModel.getTarget(ResourcesPlugin
0506:                            .getWorkspace().getRoot(), this .sourcePath, true);
0507:                    if (target instanceof  IResource) {
0508:                        if (target instanceof  IContainer) {
0509:                            computeRootPath((IContainer) target,
0510:                                    firstLevelPackageNames,
0511:                                    containsADefaultPackage, tempRoots);
0512:                        }
0513:                    } else if (target instanceof  File) {
0514:                        File file = (File) target;
0515:                        if (file.isDirectory()) {
0516:                            computeRootPath(file, firstLevelPackageNames,
0517:                                    containsADefaultPackage, tempRoots);
0518:                        }
0519:                    }
0520:                }
0521:                int size = tempRoots.size();
0522:                if (this .rootPaths != null) {
0523:                    for (Iterator iterator = this .rootPaths.iterator(); iterator
0524:                            .hasNext();) {
0525:                        tempRoots.add(new Path((String) iterator.next()));
0526:                    }
0527:                    this .rootPaths.clear();
0528:                } else {
0529:                    this .rootPaths = new ArrayList(size);
0530:                }
0531:                size = tempRoots.size();
0532:                if (size > 0) {
0533:                    ArrayList sortedRoots = new ArrayList(tempRoots);
0534:                    if (size > 1) {
0535:                        Collections.sort(sortedRoots, new Comparator() {
0536:                            public int compare(Object o1, Object o2) {
0537:                                IPath path1 = (IPath) o1;
0538:                                IPath path2 = (IPath) o2;
0539:                                return path1.segmentCount()
0540:                                        - path2.segmentCount();
0541:                            }
0542:                        });
0543:                    }
0544:                    for (Iterator iter = sortedRoots.iterator(); iter.hasNext();) {
0545:                        IPath path = (IPath) iter.next();
0546:                        this .rootPaths.add(path.toString());
0547:                    }
0548:                }
0549:                this .areRootPathsComputed = true;
0550:                if (VERBOSE) {
0551:                    System.out
0552:                            .println("Spent " + (System.currentTimeMillis() - time) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
0553:                    System.out.println("Found " + size + " root paths"); //$NON-NLS-1$ //$NON-NLS-2$
0554:                    int i = 0;
0555:                    for (Iterator iterator = this .rootPaths.iterator(); iterator
0556:                            .hasNext();) {
0557:                        System.out
0558:                                .println("root[" + i + "]=" + ((String) iterator.next()));//$NON-NLS-1$ //$NON-NLS-2$
0559:                        i++;
0560:                    }
0561:                }
0562:            }
0563:
0564:            private void computeRootPath(File directory,
0565:                    HashSet firstLevelPackageNames, boolean hasDefaultPackage,
0566:                    Set set) {
0567:                File[] files = directory.listFiles();
0568:                boolean hasSubDirectories = false;
0569:                loop: for (int i = 0, max = files.length; i < max; i++) {
0570:                    File file = files[i];
0571:                    if (file.isDirectory()) {
0572:                        hasSubDirectories = true;
0573:                        if (firstLevelPackageNames.contains(file.getName())) {
0574:                            IPath fullPath = new Path(file.getParentFile()
0575:                                    .getPath());
0576:                            IPath rootPathEntry = fullPath.removeFirstSegments(
0577:                                    this .sourcePath.segmentCount()).setDevice(
0578:                                    null);
0579:                            set.add(rootPathEntry);
0580:                            break loop;
0581:                        } else {
0582:                            computeRootPath(file, firstLevelPackageNames,
0583:                                    hasDefaultPackage, set);
0584:                        }
0585:                    } else if (i == max - 1 && !hasSubDirectories
0586:                            && hasDefaultPackage) {
0587:                        File parentDir = file.getParentFile();
0588:                        if (parentDir.list(FILENAME_FILTER).length != 0) {
0589:                            IPath fullPath = new Path(parentDir.getPath());
0590:                            IPath rootPathEntry = fullPath.removeFirstSegments(
0591:                                    this .sourcePath.segmentCount()).setDevice(
0592:                                    null);
0593:                            set.add(rootPathEntry);
0594:                        }
0595:                    }
0596:                }
0597:            }
0598:
0599:            private void computeRootPath(IContainer container,
0600:                    HashSet firstLevelPackageNames, boolean hasDefaultPackage,
0601:                    Set set) {
0602:                try {
0603:                    IResource[] resources = container.members();
0604:                    boolean hasSubDirectories = false;
0605:                    loop: for (int i = 0, max = resources.length; i < max; i++) {
0606:                        IResource resource = resources[i];
0607:                        if (resource.getType() == IResource.FOLDER) {
0608:                            hasSubDirectories = true;
0609:                            if (firstLevelPackageNames.contains(resource
0610:                                    .getName())) {
0611:                                IPath fullPath = container.getFullPath();
0612:                                IPath rootPathEntry = fullPath
0613:                                        .removeFirstSegments(
0614:                                                this .sourcePath.segmentCount())
0615:                                        .setDevice(null);
0616:                                set.add(rootPathEntry);
0617:                                break loop;
0618:                            } else {
0619:                                computeRootPath((IFolder) resource,
0620:                                        firstLevelPackageNames,
0621:                                        hasDefaultPackage, set);
0622:                            }
0623:                        }
0624:                        if (i == max - 1 && !hasSubDirectories
0625:                                && hasDefaultPackage) {
0626:                            // check if one member is a .java file
0627:                            boolean hasJavaSourceFile = false;
0628:                            for (int j = 0; j < max; j++) {
0629:                                if (org.eclipse.jdt.internal.core.util.Util
0630:                                        .isJavaLikeFileName(resources[i]
0631:                                                .getName())) {
0632:                                    hasJavaSourceFile = true;
0633:                                    break;
0634:                                }
0635:                            }
0636:                            if (hasJavaSourceFile) {
0637:                                IPath fullPath = container.getFullPath();
0638:                                IPath rootPathEntry = fullPath
0639:                                        .removeFirstSegments(
0640:                                                this .sourcePath.segmentCount())
0641:                                        .setDevice(null);
0642:                                set.add(rootPathEntry);
0643:                            }
0644:                        }
0645:                    }
0646:                } catch (CoreException e) {
0647:                    // ignore
0648:                }
0649:            }
0650:
0651:            /**
0652:             * @see ISourceElementRequestor
0653:             */
0654:            public void enterType(TypeInfo typeInfo) {
0655:
0656:                this .typeDepth++;
0657:                if (this .typeDepth == this .types.length) { // need to grow
0658:                    System.arraycopy(this .types, 0,
0659:                            this .types = new IType[this .typeDepth * 2], 0,
0660:                            this .typeDepth);
0661:                    System
0662:                            .arraycopy(
0663:                                    this .typeNameRanges,
0664:                                    0,
0665:                                    this .typeNameRanges = new SourceRange[this .typeDepth * 2],
0666:                                    0, this .typeDepth);
0667:                    System
0668:                            .arraycopy(
0669:                                    this .typeDeclarationStarts,
0670:                                    0,
0671:                                    this .typeDeclarationStarts = new int[this .typeDepth * 2],
0672:                                    0, this .typeDepth);
0673:                    System.arraycopy(this .memberName, 0,
0674:                            this .memberName = new String[this .typeDepth * 2],
0675:                            0, this .typeDepth);
0676:                    System
0677:                            .arraycopy(
0678:                                    this .memberDeclarationStart,
0679:                                    0,
0680:                                    this .memberDeclarationStart = new int[this .typeDepth * 2],
0681:                                    0, this .typeDepth);
0682:                    System
0683:                            .arraycopy(
0684:                                    this .memberNameRange,
0685:                                    0,
0686:                                    this .memberNameRange = new SourceRange[this .typeDepth * 2],
0687:                                    0, this .typeDepth);
0688:                    System
0689:                            .arraycopy(
0690:                                    this .methodParameterTypes,
0691:                                    0,
0692:                                    this .methodParameterTypes = new char[this .typeDepth * 2][][],
0693:                                    0, this .typeDepth);
0694:                    System
0695:                            .arraycopy(
0696:                                    this .methodParameterNames,
0697:                                    0,
0698:                                    this .methodParameterNames = new char[this .typeDepth * 2][][],
0699:                                    0, this .typeDepth);
0700:                    System.arraycopy(this .typeModifiers, 0,
0701:                            this .typeModifiers = new int[this .typeDepth * 2],
0702:                            0, this .typeDepth);
0703:                }
0704:                if (typeInfo.name.length == 0) {
0705:                    this .anonymousCounter++;
0706:                    if (this .anonymousCounter == this .anonymousClassName) {
0707:                        this .types[typeDepth] = this .getType(this .binaryType
0708:                                .getElementName());
0709:                    } else {
0710:                        this .types[typeDepth] = this .getType(new String(
0711:                                typeInfo.name));
0712:                    }
0713:                } else {
0714:                    this .types[typeDepth] = this .getType(new String(
0715:                            typeInfo.name));
0716:                }
0717:                this .typeNameRanges[typeDepth] = new SourceRange(
0718:                        typeInfo.nameSourceStart, typeInfo.nameSourceEnd
0719:                                - typeInfo.nameSourceStart + 1);
0720:                this .typeDeclarationStarts[typeDepth] = typeInfo.declarationStart;
0721:
0722:                IType currentType = this .types[typeDepth];
0723:
0724:                // type parameters
0725:                if (typeInfo.typeParameters != null) {
0726:                    for (int i = 0, length = typeInfo.typeParameters.length; i < length; i++) {
0727:                        TypeParameterInfo typeParameterInfo = typeInfo.typeParameters[i];
0728:                        ITypeParameter typeParameter = currentType
0729:                                .getTypeParameter(new String(
0730:                                        typeParameterInfo.name));
0731:                        setSourceRange(
0732:                                typeParameter,
0733:                                new SourceRange(
0734:                                        typeParameterInfo.declarationStart,
0735:                                        typeParameterInfo.declarationEnd
0736:                                                - typeParameterInfo.declarationStart
0737:                                                + 1),
0738:                                new SourceRange(
0739:                                        typeParameterInfo.nameSourceStart,
0740:                                        typeParameterInfo.nameSourceEnd
0741:                                                - typeParameterInfo.nameSourceStart
0742:                                                + 1));
0743:                    }
0744:                }
0745:
0746:                // type modifiers
0747:                this .typeModifiers[typeDepth] = typeInfo.modifiers;
0748:
0749:                // categories
0750:                addCategories(currentType, typeInfo.categories);
0751:            }
0752:
0753:            /**
0754:             * @see ISourceElementRequestor
0755:             */
0756:            public void enterCompilationUnit() {
0757:                // do nothing
0758:            }
0759:
0760:            /**
0761:             * @see ISourceElementRequestor
0762:             */
0763:            public void enterConstructor(MethodInfo methodInfo) {
0764:                enterAbstractMethod(methodInfo);
0765:            }
0766:
0767:            /**
0768:             * @see ISourceElementRequestor
0769:             */
0770:            public void enterField(FieldInfo fieldInfo) {
0771:                if (typeDepth >= 0) {
0772:                    this .memberDeclarationStart[typeDepth] = fieldInfo.declarationStart;
0773:                    this .memberNameRange[typeDepth] = new SourceRange(
0774:                            fieldInfo.nameSourceStart, fieldInfo.nameSourceEnd
0775:                                    - fieldInfo.nameSourceStart + 1);
0776:                    String fieldName = new String(fieldInfo.name);
0777:                    this .memberName[typeDepth] = fieldName;
0778:
0779:                    // categories
0780:                    IType currentType = this .types[typeDepth];
0781:                    IField field = currentType.getField(fieldName);
0782:                    addCategories(field, fieldInfo.categories);
0783:                }
0784:            }
0785:
0786:            /**
0787:             * @see ISourceElementRequestor
0788:             */
0789:            public void enterInitializer(int declarationSourceStart,
0790:                    int modifiers) {
0791:                //do nothing
0792:            }
0793:
0794:            /**
0795:             * @see ISourceElementRequestor
0796:             */
0797:            public void enterMethod(MethodInfo methodInfo) {
0798:                enterAbstractMethod(methodInfo);
0799:            }
0800:
0801:            private void enterAbstractMethod(MethodInfo methodInfo) {
0802:                if (typeDepth >= 0) {
0803:                    this .memberName[typeDepth] = new String(methodInfo.name);
0804:                    this .memberNameRange[typeDepth] = new SourceRange(
0805:                            methodInfo.nameSourceStart,
0806:                            methodInfo.nameSourceEnd
0807:                                    - methodInfo.nameSourceStart + 1);
0808:                    this .memberDeclarationStart[typeDepth] = methodInfo.declarationStart;
0809:                    IType currentType = this .types[typeDepth];
0810:                    int currenTypeModifiers = this .typeModifiers[typeDepth];
0811:                    char[][] parameterTypes = methodInfo.parameterTypes;
0812:                    if (parameterTypes != null && methodInfo.isConstructor
0813:                            && currentType.getDeclaringType() != null
0814:                            && !Flags.isStatic(currenTypeModifiers)) {
0815:                        IType declaringType = currentType.getDeclaringType();
0816:                        String declaringTypeName = declaringType
0817:                                .getElementName();
0818:                        if (declaringTypeName.length() == 0) {
0819:                            IClassFile classFile = declaringType.getClassFile();
0820:                            int length = parameterTypes.length;
0821:                            char[][] newParameterTypes = new char[length + 1][];
0822:                            declaringTypeName = classFile.getElementName();
0823:                            declaringTypeName = declaringTypeName.substring(0,
0824:                                    declaringTypeName.indexOf('.'));
0825:                            newParameterTypes[0] = declaringTypeName
0826:                                    .toCharArray();
0827:                            System.arraycopy(parameterTypes, 0,
0828:                                    newParameterTypes, 1, length);
0829:                            this .methodParameterTypes[typeDepth] = newParameterTypes;
0830:                        } else {
0831:                            int length = parameterTypes.length;
0832:                            char[][] newParameterTypes = new char[length + 1][];
0833:                            newParameterTypes[0] = declaringTypeName
0834:                                    .toCharArray();
0835:                            System.arraycopy(parameterTypes, 0,
0836:                                    newParameterTypes, 1, length);
0837:                            this .methodParameterTypes[typeDepth] = newParameterTypes;
0838:                        }
0839:                    } else {
0840:                        this .methodParameterTypes[typeDepth] = parameterTypes;
0841:                    }
0842:                    this .methodParameterNames[typeDepth] = methodInfo.parameterNames;
0843:
0844:                    IMethod method = currentType
0845:                            .getMethod(
0846:                                    this .memberName[typeDepth],
0847:                                    convertTypeNamesToSigs(this .methodParameterTypes[typeDepth]));
0848:
0849:                    // type parameters
0850:                    if (methodInfo.typeParameters != null) {
0851:                        for (int i = 0, length = methodInfo.typeParameters.length; i < length; i++) {
0852:                            TypeParameterInfo typeParameterInfo = methodInfo.typeParameters[i];
0853:                            ITypeParameter typeParameter = method
0854:                                    .getTypeParameter(new String(
0855:                                            typeParameterInfo.name));
0856:                            setSourceRange(
0857:                                    typeParameter,
0858:                                    new SourceRange(
0859:                                            typeParameterInfo.declarationStart,
0860:                                            typeParameterInfo.declarationEnd
0861:                                                    - typeParameterInfo.declarationStart
0862:                                                    + 1),
0863:                                    new SourceRange(
0864:                                            typeParameterInfo.nameSourceStart,
0865:                                            typeParameterInfo.nameSourceEnd
0866:                                                    - typeParameterInfo.nameSourceStart
0867:                                                    + 1));
0868:                        }
0869:                    }
0870:
0871:                    // categories
0872:                    addCategories(method, methodInfo.categories);
0873:                }
0874:            }
0875:
0876:            /**
0877:             * @see ISourceElementRequestor
0878:             */
0879:            public void exitType(int declarationEnd) {
0880:                if (typeDepth >= 0) {
0881:                    IType currentType = this .types[typeDepth];
0882:                    setSourceRange(
0883:                            currentType,
0884:                            new SourceRange(
0885:                                    this .typeDeclarationStarts[typeDepth],
0886:                                    declarationEnd
0887:                                            - this .typeDeclarationStarts[typeDepth]
0888:                                            + 1),
0889:                            this .typeNameRanges[typeDepth]);
0890:                    this .typeDepth--;
0891:                }
0892:            }
0893:
0894:            /**
0895:             * @see ISourceElementRequestor
0896:             */
0897:            public void exitCompilationUnit(int declarationEnd) {
0898:                //do nothing
0899:            }
0900:
0901:            /**
0902:             * @see ISourceElementRequestor
0903:             */
0904:            public void exitConstructor(int declarationEnd) {
0905:                exitAbstractMethod(declarationEnd);
0906:            }
0907:
0908:            /**
0909:             * @see ISourceElementRequestor
0910:             */
0911:            public void exitField(int initializationStart, int declarationEnd,
0912:                    int declarationSourceEnd) {
0913:                if (typeDepth >= 0) {
0914:                    IType currentType = this .types[typeDepth];
0915:                    setSourceRange(
0916:                            currentType.getField(this .memberName[typeDepth]),
0917:                            new SourceRange(
0918:                                    this .memberDeclarationStart[typeDepth],
0919:                                    declarationEnd
0920:                                            - this .memberDeclarationStart[typeDepth]
0921:                                            + 1),
0922:                            this .memberNameRange[typeDepth]);
0923:                }
0924:            }
0925:
0926:            /**
0927:             * @see ISourceElementRequestor
0928:             */
0929:            public void exitInitializer(int declarationEnd) {
0930:                // implements abstract method
0931:            }
0932:
0933:            /**
0934:             * @see ISourceElementRequestor
0935:             */
0936:            public void exitMethod(int declarationEnd, int defaultValueStart,
0937:                    int defaultValueEnd) {
0938:                exitAbstractMethod(declarationEnd);
0939:            }
0940:
0941:            private void exitAbstractMethod(int declarationEnd) {
0942:                if (typeDepth >= 0) {
0943:                    IType currentType = this .types[typeDepth];
0944:                    SourceRange sourceRange = new SourceRange(
0945:                            this .memberDeclarationStart[typeDepth],
0946:                            declarationEnd
0947:                                    - this .memberDeclarationStart[typeDepth]
0948:                                    + 1);
0949:                    IMethod method = currentType
0950:                            .getMethod(
0951:                                    this .memberName[typeDepth],
0952:                                    convertTypeNamesToSigs(this .methodParameterTypes[typeDepth]));
0953:                    setSourceRange(method, sourceRange,
0954:                            this .memberNameRange[typeDepth]);
0955:                    setMethodParameterNames(method,
0956:                            this .methodParameterNames[typeDepth]);
0957:                }
0958:            }
0959:
0960:            /**
0961:             * Locates and returns source code for the given (binary) type, in this
0962:             * SourceMapper's ZIP file, or returns <code>null</code> if source
0963:             * code cannot be found.
0964:             */
0965:            public char[] findSource(IType type, IBinaryType info) {
0966:                if (!type.isBinary()) {
0967:                    return null;
0968:                }
0969:                String simpleSourceFileName = ((BinaryType) type)
0970:                        .getSourceFileName(info);
0971:                if (simpleSourceFileName == null) {
0972:                    return null;
0973:                }
0974:                return findSource(type, simpleSourceFileName);
0975:            }
0976:
0977:            /**
0978:             * Locates and returns source code for the given (binary) type, in this
0979:             * SourceMapper's ZIP file, or returns <code>null</code> if source
0980:             * code cannot be found.
0981:             * The given simpleSourceFileName is the .java file name (without the enclosing
0982:             * folder) used to create the given type (e.g. "A.java" for x/y/A$Inner.class)
0983:             */
0984:            public char[] findSource(IType type, String simpleSourceFileName) {
0985:                long time = 0;
0986:                if (VERBOSE) {
0987:                    time = System.currentTimeMillis();
0988:                }
0989:                PackageFragment pkgFrag = (PackageFragment) type
0990:                        .getPackageFragment();
0991:                String name = org.eclipse.jdt.internal.core.util.Util
0992:                        .concatWith(pkgFrag.names, simpleSourceFileName, '/');
0993:
0994:                char[] source = null;
0995:
0996:                if (this .rootPath != null) {
0997:                    source = getSourceForRootPath(this .rootPath, name);
0998:                }
0999:
1000:                if (source == null) {
1001:                    computeAllRootPaths(type);
1002:                    if (this .rootPaths != null) {
1003:                        loop: for (Iterator iterator = this .rootPaths
1004:                                .iterator(); iterator.hasNext();) {
1005:                            String currentRootPath = (String) iterator.next();
1006:                            if (!currentRootPath.equals(this .rootPath)) {
1007:                                source = getSourceForRootPath(currentRootPath,
1008:                                        name);
1009:                                if (source != null) {
1010:                                    // remember right root path
1011:                                    this .rootPath = currentRootPath;
1012:                                    break loop;
1013:                                }
1014:                            }
1015:                        }
1016:                    }
1017:                }
1018:                if (VERBOSE) {
1019:                    System.out
1020:                            .println("spent " + (System.currentTimeMillis() - time) + "ms for " + type.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
1021:                }
1022:                return source;
1023:            }
1024:
1025:            private char[] getSourceForRootPath(String currentRootPath,
1026:                    String name) {
1027:                String newFullName;
1028:                if (!currentRootPath
1029:                        .equals(IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH)) {
1030:                    if (currentRootPath.endsWith("/")) { //$NON-NLS-1$
1031:                        newFullName = currentRootPath + name;
1032:                    } else {
1033:                        newFullName = currentRootPath + '/' + name;
1034:                    }
1035:                } else {
1036:                    newFullName = name;
1037:                }
1038:                return this .findSource(newFullName);
1039:            }
1040:
1041:            public char[] findSource(String fullName) {
1042:                char[] source = null;
1043:                if (Util.isArchiveFileName(this .sourcePath.lastSegment())) {
1044:                    // try to get the entry
1045:                    ZipEntry entry = null;
1046:                    ZipFile zip = null;
1047:                    JavaModelManager manager = JavaModelManager
1048:                            .getJavaModelManager();
1049:                    try {
1050:                        zip = manager.getZipFile(this .sourcePath);
1051:                        entry = zip.getEntry(fullName);
1052:                        if (entry != null) {
1053:                            // now read the source code
1054:                            source = readSource(entry, zip);
1055:                        }
1056:                    } catch (CoreException e) {
1057:                        return null;
1058:                    } finally {
1059:                        manager.closeZipFile(zip); // handle null case
1060:                    }
1061:                } else {
1062:                    Object target = JavaModel.getTarget(ResourcesPlugin
1063:                            .getWorkspace().getRoot(), this .sourcePath, true);
1064:                    if (target instanceof  IResource) {
1065:                        if (target instanceof  IContainer) {
1066:                            IResource res = ((IContainer) target)
1067:                                    .findMember(fullName);
1068:                            if (res instanceof  IFile) {
1069:                                try {
1070:                                    source = org.eclipse.jdt.internal.core.util.Util
1071:                                            .getResourceContentsAsCharArray((IFile) res);
1072:                                } catch (JavaModelException e) {
1073:                                    // ignore
1074:                                }
1075:                            }
1076:                        }
1077:                    } else if (target instanceof  File) {
1078:                        File file = (File) target;
1079:                        if (file.isDirectory()) {
1080:                            File sourceFile = new File(file, fullName);
1081:                            if (sourceFile.isFile()) {
1082:                                try {
1083:                                    source = Util.getFileCharContent(
1084:                                            sourceFile, this .encoding);
1085:                                } catch (IOException e) {
1086:                                    // ignore
1087:                                }
1088:                            }
1089:                        }
1090:                    }
1091:                }
1092:                return source;
1093:            }
1094:
1095:            /**
1096:             * Returns the SourceRange for the name of the given element, or
1097:             * {-1, -1} if no source range is known for the name of the element.
1098:             */
1099:            public SourceRange getNameRange(IJavaElement element) {
1100:                switch (element.getElementType()) {
1101:                case IJavaElement.METHOD:
1102:                    if (((IMember) element).isBinary()) {
1103:                        IJavaElement[] el = getUnqualifiedMethodHandle(
1104:                                (IMethod) element, false);
1105:                        if (el[1] != null
1106:                                && this .sourceRanges.get(el[0]) == null) {
1107:                            element = getUnqualifiedMethodHandle(
1108:                                    (IMethod) element, true)[0];
1109:                        } else {
1110:                            element = el[0];
1111:                        }
1112:                    }
1113:                    break;
1114:                case IJavaElement.TYPE_PARAMETER:
1115:                    IJavaElement parent = element.getParent();
1116:                    if (parent.getElementType() == IJavaElement.METHOD) {
1117:                        IMethod method = (IMethod) parent;
1118:                        if (method.isBinary()) {
1119:                            IJavaElement[] el = getUnqualifiedMethodHandle(
1120:                                    method, false);
1121:                            if (el[1] != null
1122:                                    && this .sourceRanges.get(el[0]) == null) {
1123:                                method = (IMethod) getUnqualifiedMethodHandle(
1124:                                        method, true)[0];
1125:                            } else {
1126:                                method = (IMethod) el[0];
1127:                            }
1128:                            element = method.getTypeParameter(element
1129:                                    .getElementName());
1130:                        }
1131:                    }
1132:                }
1133:                SourceRange[] ranges = (SourceRange[]) this .sourceRanges
1134:                        .get(element);
1135:                if (ranges == null) {
1136:                    return UNKNOWN_RANGE;
1137:                } else {
1138:                    return ranges[1];
1139:                }
1140:            }
1141:
1142:            /**
1143:             * Returns parameters names for the given method, or
1144:             * null if no parameter names are known for the method.
1145:             */
1146:            public char[][] getMethodParameterNames(IMethod method) {
1147:                if (method.isBinary()) {
1148:                    IJavaElement[] el = getUnqualifiedMethodHandle(method,
1149:                            false);
1150:                    if (el[1] != null && this .parameterNames.get(el[0]) == null) {
1151:                        method = (IMethod) getUnqualifiedMethodHandle(method,
1152:                                true)[0];
1153:                    } else {
1154:                        method = (IMethod) el[0];
1155:                    }
1156:                }
1157:                char[][] parameters = (char[][]) this .parameterNames
1158:                        .get(method);
1159:                if (parameters == null) {
1160:                    return null;
1161:                } else {
1162:                    return parameters;
1163:                }
1164:            }
1165:
1166:            /**
1167:             * Returns the <code>SourceRange</code> for the given element, or
1168:             * {-1, -1} if no source range is known for the element.
1169:             */
1170:            public SourceRange getSourceRange(IJavaElement element) {
1171:                switch (element.getElementType()) {
1172:                case IJavaElement.METHOD:
1173:                    if (((IMember) element).isBinary()) {
1174:                        IJavaElement[] el = getUnqualifiedMethodHandle(
1175:                                (IMethod) element, false);
1176:                        if (el[1] != null
1177:                                && this .sourceRanges.get(el[0]) == null) {
1178:                            element = getUnqualifiedMethodHandle(
1179:                                    (IMethod) element, true)[0];
1180:                        } else {
1181:                            element = el[0];
1182:                        }
1183:                    }
1184:                    break;
1185:                case IJavaElement.TYPE_PARAMETER:
1186:                    IJavaElement parent = element.getParent();
1187:                    if (parent.getElementType() == IJavaElement.METHOD) {
1188:                        IMethod method = (IMethod) parent;
1189:                        if (method.isBinary()) {
1190:                            IJavaElement[] el = getUnqualifiedMethodHandle(
1191:                                    method, false);
1192:                            if (el[1] != null
1193:                                    && this .sourceRanges.get(el[0]) == null) {
1194:                                method = (IMethod) getUnqualifiedMethodHandle(
1195:                                        method, true)[0];
1196:                            } else {
1197:                                method = (IMethod) el[0];
1198:                            }
1199:                            element = method.getTypeParameter(element
1200:                                    .getElementName());
1201:                        }
1202:                    }
1203:                }
1204:                SourceRange[] ranges = (SourceRange[]) this .sourceRanges
1205:                        .get(element);
1206:                if (ranges == null) {
1207:                    return UNKNOWN_RANGE;
1208:                } else {
1209:                    return ranges[0];
1210:                }
1211:            }
1212:
1213:            /**
1214:             * Returns the type with the given <code>typeName</code>.  Returns inner classes
1215:             * as well.
1216:             */
1217:            protected IType getType(String typeName) {
1218:                if (typeName.length() == 0) {
1219:                    IJavaElement classFile = this .binaryType.getParent();
1220:                    String classFileName = classFile.getElementName();
1221:                    StringBuffer newClassFileName = new StringBuffer();
1222:                    int lastDollar = classFileName.lastIndexOf('$');
1223:                    for (int i = 0; i <= lastDollar; i++)
1224:                        newClassFileName.append(classFileName.charAt(i));
1225:                    newClassFileName.append(Integer
1226:                            .toString(this .anonymousCounter));
1227:                    PackageFragment pkg = (PackageFragment) classFile
1228:                            .getParent();
1229:                    return new BinaryType(new ClassFile(pkg, newClassFileName
1230:                            .toString()), typeName);
1231:                } else if (this .binaryType.getElementName().equals(typeName))
1232:                    return this .binaryType;
1233:                else
1234:                    return this .binaryType.getType(typeName);
1235:            }
1236:
1237:            /**
1238:             * Creates a handle that has parameter types that are not
1239:             * fully qualified so that the correct source is found.
1240:             */
1241:            protected IJavaElement[] getUnqualifiedMethodHandle(IMethod method,
1242:                    boolean noDollar) {
1243:                boolean hasDollar = false;
1244:                String[] qualifiedParameterTypes = method.getParameterTypes();
1245:                String[] unqualifiedParameterTypes = new String[qualifiedParameterTypes.length];
1246:                for (int i = 0; i < qualifiedParameterTypes.length; i++) {
1247:                    StringBuffer unqualifiedTypeSig = new StringBuffer();
1248:                    getUnqualifiedTypeSignature(qualifiedParameterTypes[i],
1249:                            0/*start*/, qualifiedParameterTypes[i].length(),
1250:                            unqualifiedTypeSig, noDollar);
1251:                    unqualifiedParameterTypes[i] = unqualifiedTypeSig
1252:                            .toString();
1253:                    hasDollar |= unqualifiedParameterTypes[i].lastIndexOf('$') != -1;
1254:                }
1255:
1256:                IJavaElement[] result = new IJavaElement[2];
1257:                result[0] = ((IType) method.getParent()).getMethod(method
1258:                        .getElementName(), unqualifiedParameterTypes);
1259:                if (hasDollar) {
1260:                    result[1] = result[0];
1261:                }
1262:                return result;
1263:            }
1264:
1265:            private int getUnqualifiedTypeSignature(String qualifiedTypeSig,
1266:                    int start, int length, StringBuffer unqualifiedTypeSig,
1267:                    boolean noDollar) {
1268:                char firstChar = qualifiedTypeSig.charAt(start);
1269:                int end = start + 1;
1270:                boolean sigStart = false;
1271:                firstPass: for (int i = start; i < length; i++) {
1272:                    char current = qualifiedTypeSig.charAt(i);
1273:                    switch (current) {
1274:                    case Signature.C_ARRAY:
1275:                    case Signature.C_SUPER:
1276:                    case Signature.C_EXTENDS:
1277:                        unqualifiedTypeSig.append(current);
1278:                        start = i + 1;
1279:                        end = start + 1;
1280:                        firstChar = qualifiedTypeSig.charAt(start);
1281:                        break;
1282:                    case Signature.C_RESOLVED:
1283:                    case Signature.C_UNRESOLVED:
1284:                    case Signature.C_TYPE_VARIABLE:
1285:                        if (!sigStart) {
1286:                            start = ++i;
1287:                            sigStart = true;
1288:                        }
1289:                        break;
1290:                    case Signature.C_NAME_END:
1291:                    case Signature.C_GENERIC_START:
1292:                        end = i;
1293:                        break firstPass;
1294:                    case Signature.C_STAR:
1295:                        unqualifiedTypeSig.append(current);
1296:                        start = i + 1;
1297:                        end = start + 1;
1298:                        firstChar = qualifiedTypeSig.charAt(start);
1299:                        break;
1300:                    case Signature.C_GENERIC_END:
1301:                        return i;
1302:                    case Signature.C_DOT:
1303:                        start = ++i;
1304:                        break;
1305:                    }
1306:                }
1307:                switch (firstChar) {
1308:                case Signature.C_RESOLVED:
1309:                case Signature.C_UNRESOLVED:
1310:                case Signature.C_TYPE_VARIABLE:
1311:                    unqualifiedTypeSig.append(Signature.C_UNRESOLVED);
1312:                    if (noDollar) {
1313:                        int lastDollar = qualifiedTypeSig.lastIndexOf('$', end);
1314:                        if (lastDollar > start)
1315:                            start = lastDollar + 1;
1316:                    }
1317:                    for (int i = start; i < length; i++) {
1318:                        char current = qualifiedTypeSig.charAt(i);
1319:                        switch (current) {
1320:                        case Signature.C_GENERIC_START:
1321:                            unqualifiedTypeSig.append(current);
1322:                            i++;
1323:                            do {
1324:                                i = getUnqualifiedTypeSignature(
1325:                                        qualifiedTypeSig, i, length,
1326:                                        unqualifiedTypeSig, noDollar);
1327:                            } while (qualifiedTypeSig.charAt(i) != Signature.C_GENERIC_END);
1328:                            unqualifiedTypeSig.append(Signature.C_GENERIC_END);
1329:                            break;
1330:                        case Signature.C_NAME_END:
1331:                            unqualifiedTypeSig.append(current);
1332:                            return i + 1;
1333:                        default:
1334:                            unqualifiedTypeSig.append(current);
1335:                            break;
1336:                        }
1337:                    }
1338:                    return length;
1339:                default:
1340:                    // primitive type or wildcard
1341:                    unqualifiedTypeSig.append(qualifiedTypeSig.substring(start,
1342:                            end));
1343:                    return end;
1344:                }
1345:            }
1346:
1347:            /**
1348:             * Maps the given source code to the given binary type and its children.
1349:             */
1350:            public void mapSource(IType type, char[] contents, IBinaryType info) {
1351:                this .mapSource(type, contents, info, null);
1352:            }
1353:
1354:            /**
1355:             * Maps the given source code to the given binary type and its children.
1356:             * If a non-null java element is passed, finds the name range for the 
1357:             * given java element without storing it.
1358:             */
1359:            public synchronized ISourceRange mapSource(IType type,
1360:                    char[] contents, IBinaryType info,
1361:                    IJavaElement elementToFind) {
1362:
1363:                this .binaryType = (BinaryType) type;
1364:
1365:                // check whether it is already mapped
1366:                if (this .sourceRanges.get(type) != null)
1367:                    return (elementToFind != null) ? getNameRange(elementToFind)
1368:                            : null;
1369:
1370:                this .importsTable.remove(this .binaryType);
1371:                this .importsCounterTable.remove(this .binaryType);
1372:                this .searchedElement = elementToFind;
1373:                this .types = new IType[1];
1374:                this .typeDeclarationStarts = new int[1];
1375:                this .typeNameRanges = new SourceRange[1];
1376:                this .typeModifiers = new int[1];
1377:                this .typeDepth = -1;
1378:                this .memberDeclarationStart = new int[1];
1379:                this .memberName = new String[1];
1380:                this .memberNameRange = new SourceRange[1];
1381:                this .methodParameterTypes = new char[1][][];
1382:                this .methodParameterNames = new char[1][][];
1383:                this .anonymousCounter = 0;
1384:
1385:                HashMap oldSourceRanges = (HashMap) this .sourceRanges.clone();
1386:                try {
1387:                    IProblemFactory factory = new DefaultProblemFactory();
1388:                    SourceElementParser parser = null;
1389:                    this .anonymousClassName = 0;
1390:                    if (info == null) {
1391:                        try {
1392:                            info = (IBinaryType) this .binaryType
1393:                                    .getElementInfo();
1394:                        } catch (JavaModelException e) {
1395:                            return null;
1396:                        }
1397:                    }
1398:                    boolean isAnonymousClass = info.isAnonymous();
1399:                    char[] fullName = info.getName();
1400:                    if (isAnonymousClass) {
1401:                        String eltName = this .binaryType.getParent()
1402:                                .getElementName();
1403:                        eltName = eltName.substring(
1404:                                eltName.lastIndexOf('$') + 1, eltName.length());
1405:                        try {
1406:                            this .anonymousClassName = Integer.parseInt(eltName);
1407:                        } catch (NumberFormatException e) {
1408:                            // ignore
1409:                        }
1410:                    }
1411:                    boolean doFullParse = hasToRetrieveSourceRangesForLocalClass(fullName);
1412:                    parser = new SourceElementParser(this , factory,
1413:                            new CompilerOptions(this .options), doFullParse,
1414:                            true/*optimize string literals*/);
1415:                    parser.javadocParser.checkDocComment = false; // disable javadoc parsing
1416:                    IJavaElement javaElement = this .binaryType
1417:                            .getCompilationUnit();
1418:                    if (javaElement == null)
1419:                        javaElement = this .binaryType.getParent();
1420:                    parser.parseCompilationUnit(new BasicCompilationUnit(
1421:                            contents, null, this .binaryType
1422:                                    .sourceFileName(info), javaElement),
1423:                            doFullParse);
1424:                    if (elementToFind != null) {
1425:                        ISourceRange range = this .getNameRange(elementToFind);
1426:                        return range;
1427:                    } else {
1428:                        return null;
1429:                    }
1430:                } finally {
1431:                    if (elementToFind != null) {
1432:                        this .sourceRanges = oldSourceRanges;
1433:                    }
1434:                    this .binaryType = null;
1435:                    this .searchedElement = null;
1436:                    this .types = null;
1437:                    this .typeDeclarationStarts = null;
1438:                    this .typeNameRanges = null;
1439:                    this .typeDepth = -1;
1440:                }
1441:            }
1442:
1443:            private char[] readSource(ZipEntry entry, ZipFile zip) {
1444:                try {
1445:                    byte[] bytes = Util.getZipEntryByteContent(entry, zip);
1446:                    if (bytes != null) {
1447:                        return Util.bytesToChar(bytes, this .encoding);
1448:                    }
1449:                } catch (IOException e) {
1450:                    // ignore
1451:                }
1452:                return null;
1453:            }
1454:
1455:            /** 
1456:             * Sets the mapping for this method to its parameter names.
1457:             *
1458:             * @see #parameterNames
1459:             */
1460:            protected void setMethodParameterNames(IMethod method,
1461:                    char[][] parameterNames) {
1462:                if (parameterNames == null) {
1463:                    parameterNames = CharOperation.NO_CHAR_CHAR;
1464:                }
1465:                this .parameterNames.put(method, parameterNames);
1466:            }
1467:
1468:            /** 
1469:             * Sets the mapping for this element to its source ranges for its source range
1470:             * and name range.
1471:             *
1472:             * @see #sourceRanges
1473:             */
1474:            protected void setSourceRange(IJavaElement element,
1475:                    SourceRange sourceRange, SourceRange nameRange) {
1476:                this .sourceRanges.put(element, new SourceRange[] { sourceRange,
1477:                        nameRange });
1478:            }
1479:
1480:            /**
1481:             * Return a char[][] array containing the imports of the attached source for the binary type
1482:             */
1483:            public char[][] getImports(BinaryType type) {
1484:                char[][] imports = (char[][]) this .importsTable.get(type);
1485:                if (imports != null) {
1486:                    int importsCounter = ((Integer) this .importsCounterTable
1487:                            .get(type)).intValue();
1488:                    if (imports.length != importsCounter) {
1489:                        System.arraycopy(imports, 0,
1490:                                (imports = new char[importsCounter][]), 0,
1491:                                importsCounter);
1492:                    }
1493:                    this .importsTable.put(type, imports);
1494:                }
1495:                return imports;
1496:            }
1497:
1498:            private boolean hasToRetrieveSourceRangesForLocalClass(
1499:                    char[] eltName) {
1500:                /*
1501:                 * A$1$B$2 : true
1502:                 * A$B$B$2 : true
1503:                 * A$C$B$D : false
1504:                 * A$F$B$D$1$F : true
1505:                 * A$F$B$D$1F : true
1506:                 * A$1 : true
1507:                 * A$B : false
1508:                 */
1509:                if (eltName == null)
1510:                    return false;
1511:                int length = eltName.length;
1512:                int dollarIndex = CharOperation.indexOf('$', eltName, 0);
1513:                while (dollarIndex != -1) {
1514:                    int nameStart = dollarIndex + 1;
1515:                    if (nameStart == length)
1516:                        return false;
1517:                    if (Character.isDigit(eltName[nameStart]))
1518:                        return true;
1519:                    dollarIndex = CharOperation
1520:                            .indexOf('$', eltName, nameStart);
1521:                }
1522:                return false;
1523:            }
1524:
1525:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.