// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.fileTypes.impl;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent;
import com.intellij.util.containers.ConcurrentBitSet;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.NotNull;

import java.util.List;

/**
 * @author peter
 */
final class IgnoredFileCache {
  private final ConcurrentBitSet myNonIgnoredIds = new ConcurrentBitSet();
  private final IgnoredPatternSet myIgnoredPatterns;
  private int myVfsEventNesting;

  IgnoredFileCache(@NotNull IgnoredPatternSet ignoredPatterns) {
    myIgnoredPatterns = ignoredPatterns;
    MessageBusConnection connect = ApplicationManager.getApplication().getMessageBus().connect();
    connect.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
      @Override
      public void before(@NotNull List<? extends VFileEvent> events) {
        // during VFS event processing the system may be in inconsistent state, don't cache it
        myVfsEventNesting++;
        clearCacheForChangedFiles(events);
      }

      @Override
      public void after(@NotNull List<? extends VFileEvent> events) {
        clearCacheForChangedFiles(events);
        myVfsEventNesting--;
      }

      private void clearCacheForChangedFiles(@NotNull List<? extends VFileEvent> events) {
        for (VFileEvent event : events) {
          if (event instanceof VFilePropertyChangeEvent) {
            VirtualFile file = event.getFile();
            if (file instanceof NewVirtualFile) {
              int id = ((NewVirtualFile)file).getId();
              myNonIgnoredIds.clear(id);
            }
          }
        }
      }
    });
  }

  void clearCache() {
    myNonIgnoredIds.clear();
  }

  boolean isFileIgnored(@NotNull VirtualFile file) {
    boolean idable = myVfsEventNesting == 0 && file instanceof NewVirtualFile;
    if (!idable) {
      return myIgnoredPatterns.isIgnored(file.getNameSequence());
    }
    int id = ((NewVirtualFile)file).getId();
    if (myNonIgnoredIds.get(id)) {
      return false;
    }

    boolean result = myIgnoredPatterns.isIgnored(file.getNameSequence());
    if (!result) {
      myNonIgnoredIds.set(id);
    }
    return result;
  }
}
@@ -1875,16 +1875,64 @@
 ngeEvent
+ && ((VFilePropertyChangeEvent)event).isRename()
 ) %7B%0A    
@@ -2402,58 +2402,24 @@
 urn 
-myIgnoredPatterns.isIgnored(file.getNameSequence()
+calcIgnored(file
 );%0A 
@@ -2538,151 +2538,335 @@
     
-boolean result = myIgnoredPatterns.isIgnored(file.getNameSequence());%0A    if (!result) %7B%0A      myNonIgnoredIds.set(id);%0A    %7D%0A    return result
+return calcAndCache(file, id);%0A  %7D%0A%0A  private boolean calcAndCache(VirtualFile file, int id) %7B%0A    boolean result = calcIgnored(file);%0A    if (!result) %7B%0A      myNonIgnoredIds.set(id);%0A    %7D%0A    return result;%0A  %7D%0A%0A  private boolean calcIgnored(VirtualFile file) %7B%0A    return myIgnoredPatterns.isIgnored(file.getNameSequence())
 ;%0A  

split IgnoredFileCache into smaller methods for faster JIT compilation