don't rely on gutter markers for run config context action update in Python scripts (PY-38551)

GitOrigin-RevId: 2602281cd73aa7013877511412aa398ccd7e3f4f
This commit is contained in:
peter
2019-10-29 08:04:10 +01:00
committed by intellij-monorepo-bot
parent 18ddaa302e
commit fc41f99f77
4 changed files with 39 additions and 1 deletions

View File

@@ -12,6 +12,7 @@ import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.TextWithMnemonic;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -61,6 +62,15 @@ public abstract class RunLineMarkerContributor {
@Nullable
public abstract Info getInfo(@NotNull PsiElement element);
/**
* @param file any file with a language this contributor is registered for
* @return whether there's no possibility that a {@link com.intellij.execution.actions.RunConfigurationProducer}'would
* return a configuration not returned by this contributor in this file. Used to speed up "Run..." context action update.
*/
public boolean producesAllPossibleConfigurations(@NotNull PsiFile file) {
return true;
}
@Nullable("null means disabled")
protected static String getText(@NotNull AnAction action, @NotNull PsiElement element) {
DataContext parent = DataManager.getInstance().getDataContext();

View File

@@ -22,7 +22,10 @@ import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.Function;
import com.intellij.util.SmartList;
import com.intellij.util.ThreeState;
@@ -172,11 +175,25 @@ public class RunLineMarkerProvider extends LineMarkerProviderDescriptor {
boolean hasRunMarkers = ContainerUtil.findInstance(
DaemonCodeAnalyzerImpl.getLineMarkers(editor.getDocument(), project),
RunLineMarkerInfo.class) != null;
file.putUserData(HAS_ANYTHING_RUNNABLE, hasRunMarkers);
FileViewProvider vp = PsiManager.getInstance(project).findViewProvider(file);
if (hasRunMarkers || (vp != null && weMayTrustRunGutterContributors(vp))) {
file.putUserData(HAS_ANYTHING_RUNNABLE, hasRunMarkers);
}
}
}
}
}
private static boolean weMayTrustRunGutterContributors(FileViewProvider vp) {
for (PsiFile file : vp.getAllFiles()) {
for (RunLineMarkerContributor contributor : RunLineMarkerContributor.EXTENSION.allForLanguage(file.getLanguage())) {
if (!contributor.producesAllPossibleConfigurations(file)) {
return false;
}
}
}
return true;
}
}
private static final Key<Boolean> HAS_ANYTHING_RUNNABLE = Key.create("HAS_ANYTHING_RUNNABLE");

View File

@@ -21,6 +21,7 @@ import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.PyTokenTypes;
@@ -56,4 +57,9 @@ public class PyRunLineMarkerContributor extends RunLineMarkerContributor {
return false;
}
}
@Override
public boolean producesAllPossibleConfigurations(@NotNull PsiFile file) {
return false;
}
}

View File

@@ -17,7 +17,9 @@ package com.jetbrains.python.codeInsight.runLineMarker;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
import com.intellij.execution.lineMarker.RunLineMarkerProvider;
import com.intellij.psi.PsiElement;
import com.intellij.util.ThreeState;
import com.jetbrains.python.fixtures.PyTestCase;
import java.util.List;
@@ -30,15 +32,18 @@ public class PyRunLineMarkerTest extends PyTestCase {
PsiElement elementWithInfo = lineMarkerInfo.getElement();
assertNotNull(elementWithInfo);
assertTrue(elementWithInfo.getParent().getText().startsWith("if"));
assertEquals(ThreeState.YES, RunLineMarkerProvider.hadAnythingRunnable(myFixture.getFile().getVirtualFile()));
}
public void testWithManyIfs() {
List<LineMarkerInfo<?>> infos = getInfos("runnable_with_ifs.py");
assertEquals("There should be only one marker", 1, infos.size());
assertEquals(ThreeState.YES, RunLineMarkerProvider.hadAnythingRunnable(myFixture.getFile().getVirtualFile()));
}
public void testNotRunnable() {
assertEquals(0, getInfos("not_runnable.py").size());
assertEquals(ThreeState.UNSURE, RunLineMarkerProvider.hadAnythingRunnable(myFixture.getFile().getVirtualFile()));
}
public void testIncorrectName() {