/** * Returns the transitive closure of buildpath entries for the given project entry. * * @param projectEntry project buildpath entry * @param expandedPath a list of entries already expanded, should be empty to begin, and contains * the result * @param expanding a list of projects that have been or are currently being expanded (to detect * cycles) * @exception CoreException if unable to expand the buildpath */ private void expandProject(IBuildpathEntry projectEntry, List expandedPath, List expanding) throws CoreException { expanding.add(projectEntry); // 1. Get the raw buildpath // 2. Replace source folder entries with a project entry IPath projectPath = projectEntry.getPath(); IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(projectPath.lastSegment()); if (res == null) { // add project entry and return expandedPath.add(projectEntry); return; } IScriptProject project = (IScriptProject) DLTKCore.create(res); if (project == null || !project.getProject().isOpen() || !project.exists()) { // add project entry and return expandedPath.add(projectEntry); return; } IBuildpathEntry[] buildPath = project.getRawBuildpath(); List unexpandedPath = new ArrayList(buildPath.length); // boolean projectAdded = false; for (int i = 0; i < buildPath.length; i++) { IBuildpathEntry buildpathEntry = buildPath[i]; if (buildpathEntry.getEntryKind() == IBuildpathEntry.BPE_SOURCE) { // sources // are // always // added unexpandedPath.add(buildpathEntry); } else { // add exported entires, as configured if (buildpathEntry.isExported()) { unexpandedPath.add(buildpathEntry); } else if (!isExportedEntriesOnly() || project.equals(getScriptProject())) { // add non exported entries from root project or if we are // including all entries unexpandedPath.add(buildpathEntry); } } } // 3. expand each project entry (except for the root project) // 4. replace each container entry with a runtime entry associated with // the project Iterator iter = unexpandedPath.iterator(); while (iter.hasNext()) { IBuildpathEntry entry = (IBuildpathEntry) iter.next(); if (entry == projectEntry) { expandedPath.add(entry); } else { switch (entry.getEntryKind()) { case IBuildpathEntry.BPE_PROJECT: if (!expanding.contains(entry)) { expandProject(entry, expandedPath, expanding); } break; case IBuildpathEntry.BPE_CONTAINER: IBuildpathContainer container = DLTKCore.getBuildpathContainer(entry.getPath(), project); int property = -1; if (container != null) { switch (container.getKind()) { case IBuildpathContainer.K_APPLICATION: property = IRuntimeBuildpathEntry.USER_ENTRY; break; case IBuildpathContainer.K_DEFAULT_SYSTEM: property = IRuntimeBuildpathEntry.STANDARD_ENTRY; break; case IBuildpathContainer.K_SYSTEM: property = IRuntimeBuildpathEntry.BOOTSTRAP_ENTRY; break; } IRuntimeBuildpathEntry r = ScriptRuntime.newRuntimeContainerBuildpathEntry( entry.getPath(), property, project); // check for duplicate/redundant entries boolean duplicate = false; BuildpathContainerInitializer initializer = DLTKCore.getBuildpathContainerInitializer(r.getPath().segment(0)); for (int i = 0; i < expandedPath.size(); i++) { Object o = expandedPath.get(i); if (o instanceof IRuntimeBuildpathEntry) { IRuntimeBuildpathEntry re = (IRuntimeBuildpathEntry) o; if (re.getType() == IRuntimeBuildpathEntry.CONTAINER) { BuildpathContainerInitializer initializer2 = DLTKCore.getBuildpathContainerInitializer(re.getPath().segment(0)); Object id1 = null; Object id2 = null; if (initializer == null) { id1 = r.getPath().segment(0); } else { id1 = initializer.getComparisonID(r.getPath(), project); } if (initializer2 == null) { id2 = re.getPath().segment(0); } else { IScriptProject context = re.getScriptProject(); if (context == null) { context = project; } id2 = initializer2.getComparisonID(re.getPath(), context); } if (id1 == null) { duplicate = id2 == null; } else { duplicate = id1.equals(id2); } if (duplicate) { break; } } } } if (!duplicate) { expandedPath.add(r); } } break; default: if (!expandedPath.contains(entry)) { expandedPath.add(entry); } break; } } } return; }
/** * Add a path to current script search scope or all project fragment roots if null. Use project * resolved classpath to retrieve and store access restriction on each classpath entry. Recurse if * dependent projects are found. * * @param scriptProject Project used to get resolved classpath entries * @param pathToAdd Path to add in case of single element or null if user want to add all project * package fragment roots * @param includeMask Mask to apply on buildpath entries * @param visitedProjects Set to avoid infinite recursion * @param referringEntry Project raw entry in referring project buildpath * @throws ModelException May happen while getting script model info */ void add( ScriptProject scriptProject, IPath pathToAdd, int includeMask, HashSet<IProject> visitedProjects, IBuildpathEntry referringEntry) throws ModelException { if (!natureFilter(scriptProject)) { return; } IProject project = scriptProject.getProject(); if (!project.isAccessible() || !visitedProjects.add(project)) return; IPath projectPath = project.getFullPath(); String projectPathString = projectPath.toString(); this.addEnclosingProjectOrArchive(projectPath); // Iterate via project fragments without buildpath entries IProjectFragment[] fragments = scriptProject.getProjectFragments(); for (int i = 0; i < fragments.length; i++) { if (fragments[i].getRawBuildpathEntry() == null) { add(fragments[i]); } } IBuildpathEntry[] entries = scriptProject.getResolvedBuildpath(); IScriptModel model = scriptProject.getModel(); ModelManager.PerProjectInfo perProjectInfo = scriptProject.getPerProjectInfo(); for (int i = 0, length = entries.length; i < length; i++) { IBuildpathEntry entry = entries[i]; AccessRuleSet access = null; BuildpathEntry cpEntry = (BuildpathEntry) entry; if (referringEntry != null) { // Add only exported entries. // Source folder are implicitly exported. if (!entry.isExported() && entry.getEntryKind() != IBuildpathEntry.BPE_SOURCE) continue; cpEntry = cpEntry.combineWith((BuildpathEntry) referringEntry); // cpEntry = // ((BuildpathEntry)referringEntry).combineWith(cpEntry); } access = cpEntry.getAccessRuleSet(); switch (entry.getEntryKind()) { case IBuildpathEntry.BPE_LIBRARY: IBuildpathEntry rawEntry = null; Map<IPath, IBuildpathEntry> rootPathToRawEntries = perProjectInfo.rootPathToRawEntries; if (rootPathToRawEntries != null) { rawEntry = rootPathToRawEntries.get(entry.getPath()); } if (rawEntry == null) { break; } switch (rawEntry.getEntryKind()) { case IBuildpathEntry.BPE_LIBRARY: case IBuildpathEntry.BPE_VARIABLE: if ((includeMask & APPLICATION_LIBRARIES) != 0) { IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { String pathToString = path.toString(); add( projectPath.toString(), "", pathToString, false /* not a package */, access); //$NON-NLS-1$ addEnclosingProjectOrArchive(path); } } break; case IBuildpathEntry.BPE_CONTAINER: IBuildpathContainer container = DLTKCore.getBuildpathContainer(rawEntry.getPath(), scriptProject); if (container == null) break; if ((container.getKind() == IBuildpathContainer.K_APPLICATION && (includeMask & APPLICATION_LIBRARIES) != 0) || (includeMask & SYSTEM_LIBRARIES) != 0) { IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { String pathToString = path.toString(); add( projectPath.toString(), "", pathToString, false /* not a package */, access); //$NON-NLS-1$ addEnclosingProjectOrArchive(path); } } break; } break; case IBuildpathEntry.BPE_PROJECT: if ((includeMask & REFERENCED_PROJECTS) != 0) { IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { add( (ScriptProject) model.getScriptProject(entry.getPath().lastSegment()), null, includeMask, visitedProjects, cpEntry); } } break; case IBuildpathEntry.BPE_SOURCE: if ((includeMask & SOURCES) != 0) { IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { add( projectPath.toString(), Util.relativePath(path, 1 /* * remove project * segment */), projectPathString, false /* * not a package */, access); } } break; } } }