UnindexedFileStatus (@NotNull VirtualFile file) { ProgressManager.checkCanceled(); // give a chance to suspend indexing if (!file.isValid() || !(file instanceof VirtualFileWithId)) { return null; } // snapshot at the beginning: if file changes while being processed, we can detect this on the following scanning FileIndexingStamp indexingStamp = indexingRequest.getFileIndexingStamp(file); FileIndexesValuesApplier.ApplicationMode applicationMode = FileBasedIndexImpl.getContentIndependentIndexesApplicationMode(); if (TRUST_INDEXING_FLAG) { if (IndexingFlag.isFileIndexed(file, indexingStamp)) { myIndexableFilesFilterHolder.addFileId(FileBasedIndex.getFileId(file), myProject); return new UnindexedFileStatusBuilder(applicationMode).build(); } } Supplier<@NotNull Boolean> checker = CachedFileType.getFileTypeChangeChecker(); FileType cachedFileType = file.getFileType(); return ReadAction.compute(() -> { if (myProject.isDisposed() || !file.isValid()) { return null; } FileType fileType = checker.get() ? cachedFileType : null; UnindexedFileStatusBuilder fileStatusBuilder = new UnindexedFileStatusBuilder(applicationMode); IndexedFileImpl indexedFile = new IndexedFileImpl(file, fileType, myProject); int inputId = FileBasedIndex.getFileId(file); boolean fileWereJustAdded = myIndexableFilesFilterHolder.addFileId(inputId, myProject) == FileAddStatus.ADDED; if (IndexingFlag.isFileIndexed(file, indexingStamp)) { boolean wasInvalidated = false; if (fileWereJustAdded) { List<ID<?, ?>> ids = IndexingStamp.getNontrivialFileIndexedStates(inputId); for (FileBasedIndexInfrastructureExtension.FileIndexingStatusProcessor processor : myStateProcessors) { for (ID<?, ?> id : ids) { if (myFileBasedIndex.needsFileContentLoading(id)) { long nowTime = System.nanoTime(); try { if (!processor.processUpToDateFile(indexedFile, inputId, id)) { wasInvalidated = true; } } finally { fileStatusBuilder.timeProcessingUpToDateFiles += (System.nanoTime() - nowTime); } } } } } if (!wasInvalidated) { IndexingStamp.flushCache(inputId); return fileStatusBuilder.build(); } } FileTypeManagerEx ex = FileTypeManagerEx.getInstanceEx(); if (!(ex instanceof FileTypeManagerImpl)) { return fileStatusBuilder.build(); } Ref<Runnable> finalization = new Ref<>(); ((FileTypeManagerImpl)ex).freezeFileTypeTemporarilyWithProvidedValueIn(file, fileType, () -> { boolean isDirectory = file.isDirectory(); FileIndexingState fileTypeIndexState = null; boolean shouldCheckContentIndexes = !isDirectory && !myFileBasedIndex.isTooLarge(file); if (shouldCheckContentIndexes) { if ((fileTypeIndexState = myFileTypeIndex.getIndexingStateForFile(inputId, indexedFile)) == FileIndexingState.OUT_DATED) { if (myFileBasedIndex.doTraceIndexUpdates()) { LOG.info("Scheduling full indexing of " + indexedFile.getFileName() + " because file type index is outdated"); } myFileBasedIndex.dropNontrivialIndexedStates(inputId); fileStatusBuilder.shouldIndex = true; shouldCheckContentIndexes = false; } } boolean fileTypeIndexAlreadyUpToData = fileTypeIndexState != null && !fileTypeIndexState.updateRequired(); Set<ID<?, ?>> appliedIndexes = myFileBasedIndex.getAppliedIndexes(inputId); for (ID<?, ?> indexId : myFileBasedIndex.getRequiredIndexes(indexedFile)) { appliedIndexes.remove(indexId); boolean needsFileContentLoading = myFileBasedIndex.needsFileContentLoading(indexId); // this is the same: (shouldCheckContentIndexes && needsFileContentLoading) || !needsFileContentLoading boolean shouldCheckAgainstSingleIndex = !needsFileContentLoading || shouldCheckContentIndexes; // if FileTypeIndex already checked, no need to check it twice if (shouldCheckAgainstSingleIndex && !(FileTypeIndex.NAME.equals(indexId) && fileTypeIndexAlreadyUpToData)) { long contentlessStartTime = needsFileContentLoading ? -1 : System.nanoTime(); // measure contentless indexes only try { applyOrScheduleRequiredIndex(indexId, fileStatusBuilder, indexedFile, inputId); } finally { if (contentlessStartTime >= 0) fileStatusBuilder.timeUpdatingContentLessIndexes += (System.nanoTime() - contentlessStartTime); } } } // remove unneeded data from indexes for (ID<?, ?> indexId : appliedIndexes) { removeIndexedValue(indexedFile, inputId, indexId, fileStatusBuilder); } if (!fileStatusBuilder.hasAppliersOrRemovers()) { finishGettingStatus(file, indexedFile, inputId, fileStatusBuilder, indexingStamp); finalization.set(EmptyRunnable.getInstance()); } else { finalization.set(() -> { long applyingStart = System.nanoTime(); try { fileStatusBuilder.removers.forEach(SingleIndexValueRemover::remove); fileStatusBuilder.appliers.forEach(SingleIndexValueApplier::apply); } finally { fileStatusBuilder.timeUpdatingContentLessIndexes += (System.nanoTime() - applyingStart); } finishGettingStatus(file, indexedFile, inputId, fileStatusBuilder, indexingStamp); }); } }); finalization.get().run(); fileStatusBuilder.explain(indexedFile, explanationLogger); return fileStatusBuilder.build(); }); }