@NotNull private List<AnnotationData> doCollect( @NotNull PsiModifierListOwner listOwner, boolean onlyWritable) { final List<PsiFile> files = findExternalAnnotationsFiles(listOwner); if (files == null) { return NO_DATA; } SmartList<AnnotationData> result = new SmartList<AnnotationData>(); String externalName = getExternalName(listOwner, false); if (externalName == null) return NO_DATA; for (PsiFile file : files) { if (!file.isValid()) continue; if (onlyWritable && !file.isWritable()) continue; MostlySingularMultiMap<String, AnnotationData> fileData = getDataFromFile(file); ContainerUtil.addAll(result, fileData.get(externalName)); } if (result.isEmpty()) { return NO_DATA; } result.trimToSize(); return result; }
@NotNull private MostlySingularMultiMap<String, AnnotationData> getDataFromFile( @NotNull final PsiFile file) { Pair<MostlySingularMultiMap<String, AnnotationData>, Long> cached = annotationFileToDataAndModStamp.get(file); final long fileModificationStamp = file.getModificationStamp(); if (cached != null && cached.getSecond() == fileModificationStamp) { return cached.getFirst(); } DataParsingSaxHandler handler = new DataParsingSaxHandler(file); try { SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); saxParser.parse(new InputSource(new StringReader(escapeAttributes(file.getText()))), handler); } catch (IOException e) { LOG.error(e); } catch (ParserConfigurationException e) { LOG.error(e); } catch (SAXException e) { LOG.error(e); } Pair<MostlySingularMultiMap<String, AnnotationData>, Long> pair = Pair.create(handler.getResult(), file.getModificationStamp()); annotationFileToDataAndModStamp.put(file, pair); return pair.first; }
protected void cacheExternalAnnotations( @NotNull String packageName, @NotNull PsiFile fromFile, @NotNull List<PsiFile> annotationFiles) { VirtualFile virtualFile = fromFile.getVirtualFile(); if (virtualFile != null) { myExternalAnnotations.put(virtualFile, annotationFiles); } }
@Override @Nullable public List<PsiFile> findExternalAnnotationsFiles(@NotNull PsiModifierListOwner listOwner) { final PsiFile containingFile = listOwner.getContainingFile(); if (!(containingFile instanceof PsiJavaFile)) { return null; } final PsiJavaFile javaFile = (PsiJavaFile) containingFile; final String packageName = javaFile.getPackageName(); final VirtualFile virtualFile = containingFile.getVirtualFile(); if (virtualFile == null) return null; final List<PsiFile> files = myExternalAnnotations.get(virtualFile); if (files == NULL_LIST) return null; if (files != null) { boolean allValid = true; for (PsiFile file : files) { allValid &= file.isValid(); } if (allValid) { return files; } } if (virtualFile == null) { return null; } Set<PsiFile> possibleAnnotationsXmls = new THashSet<PsiFile>(); for (VirtualFile root : getExternalAnnotationsRoots(virtualFile)) { final VirtualFile ext = root.findFileByRelativePath(packageName.replace('.', '/') + "/" + ANNOTATIONS_XML); if (ext == null) continue; final PsiFile psiFile = myPsiManager.findFile(ext); if (psiFile == null) continue; possibleAnnotationsXmls.add(psiFile); } List<PsiFile> result; if (possibleAnnotationsXmls.isEmpty()) { myExternalAnnotations.put(virtualFile, NULL_LIST); result = null; } else { result = new SmartList<PsiFile>(possibleAnnotationsXmls); // sorting by writability: writable go first Collections.sort( result, new Comparator<PsiFile>() { @Override public int compare(PsiFile f1, PsiFile f2) { boolean w1 = f1.isWritable(); boolean w2 = f2.isWritable(); if (w1 == w2) { return 0; } return w1 ? -1 : 1; } }); myExternalAnnotations.put(virtualFile, result); } return result; }
protected void duplicateError( @NotNull PsiFile file, @NotNull String externalName, @NotNull String text) { LOG.error(text + "; for signature: '" + externalName + "' in the " + file.getVirtualFile()); }