/* @NonNull */ @Override public Iterable<Pair<IStorage, IProject>> getStorages(/* @NonNull */ URI uri) { List<Pair<IStorage, IProject>> result = newArrayListWithCapacity(1); List<PackageFragmentRootData> packageFragmentRootDatas; synchronized (cachedPackageFragmentRootData) { packageFragmentRootDatas = newArrayList(cachedPackageFragmentRootData.values()); } Iterator<PackageFragmentRootData> iterator = packageFragmentRootDatas.iterator(); while (iterator.hasNext()) { PackageFragmentRootData data = iterator.next(); if (data.exists()) { if (data.uriPrefix == null || uri.toString().startsWith(data.uriPrefix.toString())) { IStorage storage = data.uri2Storage.get(uri); if (storage != null) { for (IPackageFragmentRoot root : data.associatedRoots.values()) { result.add(Tuples.create(storage, root.getJavaProject().getProject())); } } } } else { iterator.remove(); } } if (result.isEmpty() && uri.isArchive()) { String authority = uri.authority(); authority = authority.substring(0, authority.length() - 1); URI archiveURI = URI.createURI(authority); if (archiveURI.isFile() || archiveURI.isPlatformResource()) { IPath archivePath = new Path( archiveURI.isPlatformResource() ? archiveURI.toPlatformString(true) : archiveURI.toFileString()); for (PackageFragmentRootData data : packageFragmentRootDatas) { if (data.uriPrefix != null && archivePath.equals(data.getPath())) { // prefixes have an empty last segment. URI prefix = data.uriPrefix.lastSegment().length() == 0 ? data.uriPrefix.trimSegments(1) : data.uriPrefix; URI expectedURI = prefix.appendSegments(uri.segments()); IStorage storage = data.uri2Storage.get(expectedURI); if (storage != null) { for (IPackageFragmentRoot root : data.associatedRoots.values()) { result.add(Tuples.create(storage, root.getJavaProject().getProject())); } } } } } } return result; }
@Override public boolean isAffected( Collection<Delta> deltas, IResourceDescription candidate, IResourceDescriptions context) { Set<URI> outgoingReferences = descriptionUtils.collectOutgoingReferences(candidate); if (!outgoingReferences.isEmpty()) { for (IResourceDescription.Delta delta : deltas) if (hasChanges(delta, candidate) && outgoingReferences.contains(delta.getUri())) return true; } // this is a tradeoff - we could either check whether a given delta uri is contained // in a reachable container and check for intersecting names afterwards, or we can do // the other way round // unfortunately there is no way to decide reliably which algorithm scales better // note that this method is called for each description so we have something like a // number of deltas x number of resources which is not really nice List<IContainer> containers = null; Collection<QualifiedName> importedNames = getImportedNames(candidate); for (IResourceDescription.Delta delta : deltas) { if (hasChanges(delta, candidate)) { // not a java resource - delta's resource should be contained in a visible container // as long as we did not delete the resource URI uri = delta.getUri(); if ((uri.isPlatform() || uri.isArchive()) && delta.getNew() != null) { if (containers == null) containers = containerManager.getVisibleContainers(candidate, context); boolean descriptionIsContained = false; for (int i = 0; i < containers.size() && !descriptionIsContained; i++) { descriptionIsContained = containers.get(i).hasResourceDescription(uri); } if (!descriptionIsContained) return false; } if (isAffected(importedNames, delta.getNew()) || isAffected(importedNames, delta.getOld())) { return true; } } } return false; }
@Override public boolean isApplicable(URI uri) { return uri.isArchive(); }