private void encodeFileReference(FileReference fileReference) { start("gml:File"); final AttributesImpl atts = new AttributesImpl(); atts.addAttribute("", "xlink:arcrole", "xlink:arcrole", "", "fileReference"); atts.addAttribute("", "xlink:href", "xlink:href", "", "cid:" + fileReference.getReference()); atts.addAttribute("", "xlink:role", "xlink:role", "", fileReference.getConformanceClass()); element("gml:rangeParameters", "", atts); element("gml:fileReference", "cid:" + fileReference.getReference()); element("gml:fileStructure", ""); element("gml:mimeType", fileReference.getMimeType()); end("gml:File"); }
/** * Returns new or cached instances of PBXBuildFiles corresponding to files that may or may not * belong to an aggregate reference (see {@link AggregateReferenceType}). Files specified by the * {@code paths} argument are grouped into individual PBXBuildFiles using the given {@link * AggregateReferenceType}. Files that are standalone are not put in an aggregate reference, but * are put in a standalone PBXBuildFile in the returned sequence. */ public Iterable<PBXBuildFile> get(AggregateReferenceType type, Iterable<Path> paths) { ImmutableList.Builder<PBXBuildFile> result = new ImmutableList.Builder<>(); SetMultimap<AggregateKey, Path> keyedPaths = type.aggregates(paths); for (Map.Entry<AggregateKey, Collection<Path>> aggregation : keyedPaths.asMap().entrySet()) { if (!aggregation.getKey().isStandalone()) { ImmutableSet<Path> itemPaths = ImmutableSet.copyOf(aggregation.getValue()); result.add( aggregateBuildFile( itemPaths, type.create(aggregation.getKey(), fileReferences(itemPaths)))); } } for (Path generalResource : keyedPaths.get(AggregateKey.standalone())) { result.add(getStandalone(FileReference.of(generalResource.toString(), SourceTree.GROUP))); } return result.build(); }
@Override public Object[] getFileReferenceCompletionVariants(final FileReference reference) { final String s = reference.getText(); if (s != null && s.equals("/")) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } final CommonProcessors.CollectUniquesProcessor<PsiFileSystemItem> collector = new CommonProcessors.CollectUniquesProcessor<PsiFileSystemItem>(); final PsiElementProcessor<PsiFileSystemItem> processor = new PsiElementProcessor<PsiFileSystemItem>() { @Override public boolean execute(@NotNull PsiFileSystemItem fileSystemItem) { return new FilteringProcessor<PsiFileSystemItem>( reference.getFileReferenceSet().getReferenceCompletionFilter(), collector) .process(FileReference.getOriginalFile(fileSystemItem)); } }; List<Object> additionalItems = ContainerUtil.newArrayList(); for (PsiFileSystemItem context : reference.getContexts()) { for (final PsiElement child : context.getChildren()) { if (child instanceof PsiFileSystemItem) { processor.execute((PsiFileSystemItem) child); } } if (context instanceof FileReferenceResolver) { additionalItems.addAll(((FileReferenceResolver) context).getVariants(reference)); } } final FileType[] types = reference.getFileReferenceSet().getSuitableFileTypes(); final THashSet<PsiElement> set = new THashSet<PsiElement>(collector.getResults(), VARIANTS_HASHING_STRATEGY); final PsiElement[] candidates = PsiUtilCore.toPsiElementArray(set); final Object[] variants = new Object[candidates.length + additionalItems.size()]; for (int i = 0; i < candidates.length; i++) { PsiElement candidate = candidates[i]; Object item = reference.createLookupItem(candidate); if (item == null) { item = FileInfoManager.getFileLookupItem(candidate); } if (candidate instanceof PsiFile && item instanceof LookupElement && types.length > 0 && ArrayUtil.contains(((PsiFile) candidate).getFileType(), types)) { item = PrioritizedLookupElement.withPriority((LookupElement) item, Double.MAX_VALUE); } variants[i] = item; } for (int i = 0; i < additionalItems.size(); i++) { variants[i + candidates.length] = additionalItems.get(i); } if (!reference.getFileReferenceSet().isUrlEncoded()) { return variants; } List<Object> encodedVariants = new ArrayList<Object>(variants.length + additionalItems.size()); for (int i = 0; i < candidates.length; i++) { final PsiElement element = candidates[i]; if (element instanceof PsiNamedElement) { final PsiNamedElement psiElement = (PsiNamedElement) element; String name = psiElement.getName(); final String encoded = reference.encode(name, psiElement); if (encoded == null) continue; if (!encoded.equals(name)) { final Icon icon = psiElement.getIcon(Iconable.ICON_FLAG_READ_STATUS | Iconable.ICON_FLAG_VISIBILITY); LookupElementBuilder item = FileInfoManager.getFileLookupItem(candidates[i], encoded, icon); encodedVariants.add(item.withTailText(" (" + name + ")")); } else { encodedVariants.add(variants[i]); } } } encodedVariants.addAll(additionalItems); return ArrayUtil.toObjectArray(encodedVariants); }
/** * Returns a new or cached PBXFileReference for the given file. The name of the reference depends * on whether the file is in a localized (*.lproj) directory. If it is localized, then the name of * the reference is the name of the language (the text before ".lproj"). Otherwise, the name is * the same as the file name (e.g. Localizable.strings). This is confusing, but it is how Xcode * creates PBXFileReferences. */ private PBXFileReference fileReference(Path path) { Optional<String> language = Resources.languageOfLprojDir(path); String name = language.isPresent() ? language.get() : path.getFileName().toString(); return pbxReferences.get(FileReference.of(name, path.toString(), SourceTree.GROUP)); }
@Nullable public PsiFileSystemItem resolve() { final FileReference lastReference = getLastReference(); return lastReference == null ? null : lastReference.resolve(); }