Add statistics for venv created from requirements.txt/setup.py/environment.yml/pipfil...
[idea/community.git] / platform / projectModel-api / src / com / intellij / openapi / project / ProjectLocator.java
1 // Copyright 2000-2019 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.
2
3 /*
4  * @author max
5  */
6 package com.intellij.openapi.project;
7
8 import com.intellij.openapi.application.ApplicationManager;
9 import com.intellij.openapi.application.CachedSingletonsRegistry;
10 import com.intellij.openapi.util.ThrowableComputable;
11 import com.intellij.openapi.vfs.VirtualFile;
12 import org.jetbrains.annotations.ApiStatus;
13 import org.jetbrains.annotations.NotNull;
14 import org.jetbrains.annotations.Nullable;
15
16 import java.util.Collection;
17 import java.util.HashMap;
18 import java.util.Map;
19
20 @ApiStatus.NonExtendable
21 public abstract class ProjectLocator {
22   // called very often by StubUpdatingIndex
23   private static ProjectLocator ourInstance = CachedSingletonsRegistry.markCachedField(ProjectLocator.class);
24
25   private static final ThreadLocal<Map<VirtualFile, Project>> ourPreferredProjects = ThreadLocal.withInitial(() -> new HashMap<>());
26
27   public static ProjectLocator getInstance() {
28     ProjectLocator result = ourInstance;
29     if (result == null) {
30       result = ApplicationManager.getApplication().getService(ProjectLocator.class);
31       ourInstance = result;
32     }
33     return result;
34   }
35
36   /**
37    * Returns an open project which contains the given file.
38    * This is a guess-method, so if several projects contain the file, only one will be returned.
39    * Also a project may be returned though it doesn't contain the file for sure (see implementations).
40    * @param file file to be located in projects.
41    * @return project which probably contains the file, or null if couldn't guess (for example, there are no open projects).
42    */
43   @Nullable
44   public abstract Project guessProjectForFile(@Nullable VirtualFile file);
45
46   /**
47   * Gets all open projects containing the given file.
48   * If none does, an empty list is returned.
49   * @param file file to be located in projects.
50   * @return list of open projects containing this file.
51   */
52   @NotNull
53   public abstract Collection<Project> getProjectsForFile(@NotNull VirtualFile file);
54
55   public static <T, E extends Throwable> T computeWithPreferredProject(@NotNull VirtualFile file,
56                                                                        @NotNull Project preferredProject,
57                                                                        @NotNull ThrowableComputable<T, E> runnable) throws E {
58     Map<VirtualFile, Project> local = ourPreferredProjects.get();
59     Project prev = local.put(file, preferredProject);
60     try {
61       return runnable.compute();
62     }
63     finally {
64       if (prev == null) {
65         local.remove(file);
66       }
67       else {
68         local.put(file, prev);
69       }
70     }
71   }
72
73   @Nullable
74   static Project getPreferredProject(@NotNull VirtualFile file) {
75     return ourPreferredProjects.get().get(file);
76   }
77 }