mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
PY-51096 Don't get list of sdks inside inspections
(cherry picked from commit 3f0c00cbf6c583211d7cbc576a04bfb35d5edd1d) IJ-MR-15111 GitOrigin-RevId: 055b6649689e75fa5039f43c6ab4c9f61a314ad6
This commit is contained in:
committed by
intellij-monorepo-bot
parent
286a57eef9
commit
7501339247
@@ -79,5 +79,6 @@
|
||||
<orderEntry type="library" name="jcef" level="project" />
|
||||
<orderEntry type="library" name="Velocity" level="project" />
|
||||
<orderEntry type="library" name="jna" level="project" />
|
||||
<orderEntry type="library" name="caffeine" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -13,6 +13,15 @@
|
||||
<!-- Enable command-line language -->
|
||||
<xi:include href="/META-INF/command-line.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<projectListeners>
|
||||
<listener
|
||||
class="com.jetbrains.python.inspections.PyInterpreterInspection$Visitor$CacheCleaner"
|
||||
topic="com.intellij.openapi.roots.ModuleRootListener"/>
|
||||
<listener
|
||||
class="com.jetbrains.python.inspections.PyInterpreterInspection$Visitor$CacheCleaner"
|
||||
topic="com.intellij.openapi.projectRoots.ProjectJdkTable$Listener"/>
|
||||
</projectListeners>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<library.type implementation="com.jetbrains.python.library.PythonLibraryType"/>
|
||||
<renameHandler implementation="com.jetbrains.python.magicLiteral.PyMagicLiteralRenameHandler"/>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright 2000-2020 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.jetbrains.python.inspections;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
@@ -9,18 +11,19 @@ import com.intellij.codeInspection.util.InspectionMessage;
|
||||
import com.intellij.codeInspection.util.IntentionFamilyName;
|
||||
import com.intellij.codeInspection.util.IntentionName;
|
||||
import com.intellij.ide.actions.ShowSettingsUtilImpl;
|
||||
import com.intellij.openapi.application.ex.ApplicationUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.options.ex.ConfigurableExtensionPointUtil;
|
||||
import com.intellij.openapi.options.ex.ConfigurableVisitor;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
|
||||
import com.intellij.openapi.roots.ModuleRootEvent;
|
||||
import com.intellij.openapi.roots.ModuleRootListener;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
|
||||
@@ -31,6 +34,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PythonIdeLanguageCustomization;
|
||||
@@ -48,10 +52,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -73,6 +77,21 @@ public final class PyInterpreterInspection extends PyInspection {
|
||||
}
|
||||
|
||||
public static class Visitor extends PyInspectionVisitor {
|
||||
/** Invalidated by {@link CacheCleaner}. */
|
||||
private static final AsyncLoadingCache<Module, List<PyDetectedSdk>> DETECTED_ASSOCIATED_ENVS_CACHE = Caffeine.newBuilder()
|
||||
.executor(AppExecutorUtil.getAppExecutorService())
|
||||
|
||||
// Even though various listeners invalidate the cache on many actions, it's unfeasible to track for venv/conda interpreters
|
||||
// creation performed outside the IDE.
|
||||
// 20 seconds timeout is taken at random.
|
||||
.expireAfterWrite(Duration.ofSeconds(20))
|
||||
|
||||
.weakKeys()
|
||||
.buildAsync(module -> {
|
||||
final List<Sdk> existingSdks = getExistingSdks();
|
||||
final UserDataHolderBase context = new UserDataHolderBase();
|
||||
return PySdkExtKt.detectAssociatedEnvironments(module, existingSdks, context);
|
||||
});
|
||||
|
||||
public Visitor(@Nullable ProblemsHolder holder,
|
||||
@NotNull TypeEvalContext context) {
|
||||
@@ -171,17 +190,19 @@ public final class PyInterpreterInspection extends PyInspection {
|
||||
final UserDataHolderBase context = new UserDataHolderBase();
|
||||
|
||||
List<PyDetectedSdk> detectedAssociatedEnvs = Collections.emptyList();
|
||||
try {
|
||||
detectedAssociatedEnvs = ApplicationUtil.runWithCheckCanceled(
|
||||
() -> PySdkExtKt.detectAssociatedEnvironments(module, existingSdks, context),
|
||||
ProgressManager.getInstance().getProgressIndicator()
|
||||
);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.warn(e);
|
||||
while (true) {
|
||||
try {
|
||||
// Beware that this thread holds the read lock. Shouldn't wait too much.
|
||||
detectedAssociatedEnvs = DETECTED_ASSOCIATED_ENVS_CACHE.get(module).get(10, TimeUnit.MILLISECONDS);
|
||||
break;
|
||||
}
|
||||
catch (InterruptedException | TimeoutException ignored) {
|
||||
ProgressManager.checkCanceled();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.warn("Failed to get suitable sdk fix for name " + name + " and module " + module, e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
final var detectedAssociatedSdk = ContainerUtil.getFirstItem(detectedAssociatedEnvs);
|
||||
if (detectedAssociatedSdk != null) return new UseDetectedInterpreterFix(detectedAssociatedSdk, existingSdks, true, module);
|
||||
@@ -285,6 +306,32 @@ public final class PyInterpreterInspection extends PyInspection {
|
||||
private static String getEnvRootName(@Nullable File envRoot) {
|
||||
return envRoot == null ? null : PathUtil.getFileName(envRoot.getPath());
|
||||
}
|
||||
|
||||
private static class CacheCleaner implements ModuleRootListener, ProjectJdkTable.Listener {
|
||||
@Override
|
||||
public void beforeRootsChange(@NotNull ModuleRootEvent event) {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jdkAdded(@NotNull Sdk jdk) {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jdkRemoved(@NotNull Sdk jdk) {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jdkNameChanged(@NotNull Sdk jdk, @NotNull String previousName) {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void invalidate() {
|
||||
DETECTED_ASSOCIATED_ENVS_CACHE.synchronous().invalidateAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
Reference in New Issue
Block a user