<commit_before>/*
 * Copyright 2000-2012 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.intellij.openapi.roots.impl;

import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.file.exclude.ProjectFileExclusionManager;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ContentIterator;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileFilter;
import org.jetbrains.annotations.NotNull;

import java.util.Collections;
import java.util.List;

public class ProjectFileIndexImpl implements ProjectFileIndex {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.ProjectFileIndexImpl");

  private final Project myProject;
  private final FileTypeRegistry myFileTypeRegistry;
  private final DirectoryIndex myDirectoryIndex;
  private final ContentFilter myContentFilter;
  private final ProjectFileExclusionManager myFileExclusionManager;

  public ProjectFileIndexImpl(@NotNull Project project, @NotNull DirectoryIndex directoryIndex, @NotNull FileTypeRegistry fileTypeManager) {
    myProject = project;

    myDirectoryIndex = directoryIndex;
    myFileTypeRegistry = fileTypeManager;
    myContentFilter = new ContentFilter();
    myFileExclusionManager = ProjectFileExclusionManager.SERVICE.getInstance(project);
  }

  public boolean iterateContent(@NotNull ContentIterator iterator) {
    Module[] modules = ModuleManager.getInstance(myProject).getModules();
    for (Module module : modules) {
      VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
      for (VirtualFile contentRoot : contentRoots) {
        DirectoryInfo info = getInfoForDirectory(contentRoot);
        if (info == null) continue; // is excluded or ignored
        if (!module.equals(info.module)) continue; // maybe 2 modules have the same content root?

        VirtualFile parent = contentRoot.getParent();
        if (parent != null) {
          DirectoryInfo parentInfo = getInfoForDirectory(parent);
          if (parentInfo != null && parentInfo.module != null) continue; // inner content - skip it
        }

        boolean finished = FileIndexImplUtil.iterateRecursively(contentRoot, myContentFilter, iterator);
        if (!finished) return false;
      }
    }

    return true;
  }

  private DirectoryInfo getInfoForDirectory(@NotNull VirtualFile file) {
    //if ((! myProject.isOpen()) || myProject.isDisposed()) {
    //  if (StartupManagerEx.getInstanceEx(myProject).startupActivityPassed()) {
    //    throw new ProcessCanceledException();
    //  }
    //}
    return myDirectoryIndex.getInfoForDirectory(file);
  }

  public boolean iterateContentUnderDirectory(@NotNull VirtualFile dir, @NotNull ContentIterator iterator) {
    return FileIndexImplUtil.iterateRecursively(dir, myContentFilter, iterator);
  }

  public boolean isIgnored(@NotNull VirtualFile file) {
    if (myFileTypeRegistry.isFileIgnored(file)) return true;
    if (myFileExclusionManager != null && myFileExclusionManager.isExcluded(file)) return true;
    VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return false;

    DirectoryInfo info = getInfoForDirectory(dir);
    if (info != null) return false;
    if (myDirectoryIndex.isProjectExcludeRoot(dir)) return true;

    VirtualFile parent = dir.getParent();
    while (true) {
      if (parent == null) return false;
      DirectoryInfo parentInfo = getInfoForDirectory(parent);
      if (parentInfo != null) return true;
      if (myDirectoryIndex.isProjectExcludeRoot(parent)) return true;
      parent = parent.getParent();
    }
  }

  public Module getModuleForFile(@NotNull VirtualFile file) {
    if (file instanceof VirtualFileWindow) file = ((VirtualFileWindow)file).getDelegate();
    VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return null;
    DirectoryInfo info = getInfoForDirectory(dir);
    if (info == null) return null;
    return info.module;
  }

  @NotNull
  public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile file) {
    VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return Collections.emptyList();
    final DirectoryInfo info = getInfoForDirectory(dir);
    if (info == null) return Collections.emptyList();
    return Collections.unmodifiableList(info.getOrderEntries());
  }

  public VirtualFile getClassRootForFile(@NotNull VirtualFile file) {
    VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return null;
    final DirectoryInfo info = getInfoForDirectory(dir);
    if (info == null) return null;
    return info.libraryClassRoot;
  }

  public VirtualFile getSourceRootForFile(@NotNull VirtualFile file) {
    final VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return null;
    final DirectoryInfo info = getInfoForDirectory(dir);
    if (info == null) return null;
    return info.sourceRoot;
  }

  public VirtualFile getContentRootForFile(@NotNull VirtualFile file) {
    VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return null;
    final DirectoryInfo info = getInfoForDirectory(dir);
    if (info == null) return null;
    return info.contentRoot;
  }

  public String getPackageNameByDirectory(@NotNull VirtualFile dir) {
    LOG.assertTrue(dir.isDirectory());
    return myDirectoryIndex.getPackageName(dir);
  }

  public boolean isContentSourceFile(@NotNull VirtualFile file) {
    return !file.isDirectory() &&
           !myFileTypeRegistry.isFileIgnored(file) &&
           isInSourceContent(file);
  }

  public boolean isLibraryClassFile(@NotNull VirtualFile file) {
    if (file.isDirectory()) return false;
    if (myFileTypeRegistry.isFileIgnored(file)) return false;
    VirtualFile parent = file.getParent();
    DirectoryInfo parentInfo = getInfoForDirectory(parent);
    return parentInfo != null && parentInfo.libraryClassRoot != null;
  }

  public boolean isInSource(@NotNull VirtualFile fileOrDir) {
    if (fileOrDir.isDirectory()) {
      DirectoryInfo info = getInfoForDirectory(fileOrDir);
      return info != null && (info.isInModuleSource || info.isInLibrarySource);
    }
    else {
      VirtualFile parent = fileOrDir.getParent();
      return parent != null && isInSource(parent);
    }
  }

  public boolean isInLibraryClasses(@NotNull VirtualFile fileOrDir) {
    DirectoryInfo info = getInfoForDirectory(fileOrDir);
    if (info != null) {     
      return info.libraryClassRoot != null;<commit_msg>Fix scope bugs in ProjectFileIndex for JS libraries<commit_after>/*
 * Copyright 2000-2012 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.intellij.openapi.roots.impl;

import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.file.exclude.ProjectFileExclusionManager;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ContentIterator;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileFilter;
import org.jetbrains.annotations.NotNull;

import java.util.Collections;
import java.util.List;

public class ProjectFileIndexImpl implements ProjectFileIndex {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.ProjectFileIndexImpl");

  private final Project myProject;
  private final FileTypeRegistry myFileTypeRegistry;
  private final DirectoryIndex myDirectoryIndex;
  private final ContentFilter myContentFilter;
  private final ProjectFileExclusionManager myFileExclusionManager;

  public ProjectFileIndexImpl(@NotNull Project project, @NotNull DirectoryIndex directoryIndex, @NotNull FileTypeRegistry fileTypeManager) {
    myProject = project;

    myDirectoryIndex = directoryIndex;
    myFileTypeRegistry = fileTypeManager;
    myContentFilter = new ContentFilter();
    myFileExclusionManager = ProjectFileExclusionManager.SERVICE.getInstance(project);
  }

  public boolean iterateContent(@NotNull ContentIterator iterator) {
    Module[] modules = ModuleManager.getInstance(myProject).getModules();
    for (Module module : modules) {
      VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
      for (VirtualFile contentRoot : contentRoots) {
        DirectoryInfo info = getInfoForDirectory(contentRoot);
        if (info == null) continue; // is excluded or ignored
        if (!module.equals(info.module)) continue; // maybe 2 modules have the same content root?

        VirtualFile parent = contentRoot.getParent();
        if (parent != null) {
          DirectoryInfo parentInfo = getInfoForDirectory(parent);
          if (parentInfo != null && parentInfo.module != null) continue; // inner content - skip it
        }

        boolean finished = FileIndexImplUtil.iterateRecursively(contentRoot, myContentFilter, iterator);
        if (!finished) return false;
      }
    }

    return true;
  }

  private DirectoryInfo getInfoForDirectory(@NotNull VirtualFile file) {
    //if ((! myProject.isOpen()) || myProject.isDisposed()) {
    //  if (StartupManagerEx.getInstanceEx(myProject).startupActivityPassed()) {
    //    throw new ProcessCanceledException();
    //  }
    //}
    return myDirectoryIndex.getInfoForDirectory(file);
  }

  public boolean iterateContentUnderDirectory(@NotNull VirtualFile dir, @NotNull ContentIterator iterator) {
    return FileIndexImplUtil.iterateRecursively(dir, myContentFilter, iterator);
  }

  public boolean isIgnored(@NotNull VirtualFile file) {
    if (myFileTypeRegistry.isFileIgnored(file)) return true;
    if (myFileExclusionManager != null && myFileExclusionManager.isExcluded(file)) return true;
    VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return false;

    DirectoryInfo info = getInfoForDirectory(dir);
    if (info != null) return false;
    if (myDirectoryIndex.isProjectExcludeRoot(dir)) return true;

    VirtualFile parent = dir.getParent();
    while (true) {
      if (parent == null) return false;
      DirectoryInfo parentInfo = getInfoForDirectory(parent);
      if (parentInfo != null) return true;
      if (myDirectoryIndex.isProjectExcludeRoot(parent)) return true;
      parent = parent.getParent();
    }
  }

  public Module getModuleForFile(@NotNull VirtualFile file) {
    if (file instanceof VirtualFileWindow) file = ((VirtualFileWindow)file).getDelegate();
    VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return null;
    DirectoryInfo info = getInfoForDirectory(dir);
    if (info == null) return null;
    return info.module;
  }

  @NotNull
  public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile file) {
    VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return Collections.emptyList();
    final DirectoryInfo info = getInfoForDirectory(dir);
    if (info == null) return Collections.emptyList();
    return Collections.unmodifiableList(info.getOrderEntries());
  }

  public VirtualFile getClassRootForFile(@NotNull VirtualFile file) {
    VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return null;
    final DirectoryInfo info = getInfoForDirectory(dir);
    if (info == null) return null;
    return info.libraryClassRoot;
  }

  public VirtualFile getSourceRootForFile(@NotNull VirtualFile file) {
    final VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return null;
    final DirectoryInfo info = getInfoForDirectory(dir);
    if (info == null) return null;
    return info.sourceRoot;
  }

  public VirtualFile getContentRootForFile(@NotNull VirtualFile file) {
    VirtualFile dir = file.isDirectory() ? file : file.getParent();
    if (dir == null) return null;
    final DirectoryInfo info = getInfoForDirectory(dir);
    if (info == null) return null;
    return info.contentRoot;
  }

  public String getPackageNameByDirectory(@NotNull VirtualFile dir) {
    LOG.assertTrue(dir.isDirectory());
    return myDirectoryIndex.getPackageName(dir);
  }

  public boolean isContentSourceFile(@NotNull VirtualFile file) {
    return !file.isDirectory() &&
           !myFileTypeRegistry.isFileIgnored(file) &&
           isInSourceContent(file);
  }

  public boolean isLibraryClassFile(@NotNull VirtualFile file) {
    if (file.isDirectory()) return false;
    if (myFileTypeRegistry.isFileIgnored(file)) return false;
    VirtualFile parent = file.getParent();
    DirectoryInfo parentInfo = getInfoForDirectory(parent);
    return parentInfo != null && parentInfo.libraryClassRoot != null;
  }

  public boolean isInSource(@NotNull VirtualFile fileOrDir) {
    DirectoryInfo info = getInfoForDirectory(fileOrDir);
    if (info != null) {
      return info.isInModuleSource || info.isInLibrarySource;
    }
    else {
      VirtualFile parent = fileOrDir.getParent();
      return parent != null && isInSource(parent);
    }
  }

  public boolean isInLibraryClasses(@NotNull VirtualFile fileOrDir) {
    DirectoryInfo info = getInfoForDirectory(fileOrDir);
    if (info != null) {     
      return info.libraryClassRoot != null;
{'fraction_non_alphanumeric': 0.09588858532684748, 'fraction_numerical': 0.00173252482174985, 'mean_word_length': 4.260427620049071, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3232943', 'n_tokens_mistral': 4138, 'n_tokens_neox': 4016, 'n_words': 1091}