void (@NotNull Collection<? extends VirtualFile> files) { if (files.isEmpty()) return; List<VirtualFile> changed = new ArrayList<>(); List<VirtualFile> crashed = new ArrayList<>(); for (VirtualFile file : files) { if (toLog()) { log("F: reDetect(" + file.getName() + ") " + file.getName()); } int id = ((VirtualFileWithId)file).getId(); long flags = packedFlags.get(id); FileType before = ObjectUtils.notNull(textOrBinaryFromCachedFlags(flags), ObjectUtils.notNull(getFileTypeDetectedFromContent(file), PlainTextFileType.INSTANCE)); FileType after = myFileTypeManager.getByFile(file); if (toLog()) { log("F: reDetect(" + file.getName() + ") prepare to redetect. flags: " + readableFlags(flags) + "; beforeType: " + before.getName() + "; afterByFileType: " + (after == null ? null : after.getName())); } if (after == null || after == DetectedByContentFileType.INSTANCE) { try { after = detectFromContentAndCache(file, null, after); } catch (IOException e) { crashed.add(file); if (toLog()) { log("F: reDetect(" + file.getName() + ") " + "before: " + before.getName() + "; after: crashed with " + e.getMessage() + "; now getFileType()=" + file.getFileType().getName() + "; getUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY): " + file.getUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY)); } continue; } } else { // back to standard file type // detected by conventional methods, no need to run detect-from-content file.putUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY, null); flags = 0; packedFlags.set(id, flags); } if (toLog()) { log("F: reDetect(" + file.getName() + ") before: " + before.getName() + "; after: " + after.getName() + "; now getFileType()=" + file.getFileType().getName() + "; getUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY): " + file.getUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY)); } if (before != after) { changed.add(file); } } if (!changed.isEmpty()) { reparseLater(changed); } if (!crashed.isEmpty()) { // do not re-scan locked or invalid files too often to avoid constant disk thrashing if that condition is permanent AppExecutorUtil.getAppScheduledExecutorService().schedule(() -> reparseLater(crashed), 10, TimeUnit.SECONDS); } }