PY-41923 Migrate ReST configuration producers to newer dynamic plugins-ready API

The main problem with them is that due to an odd design decision they both share
the same configuration type -- RestRunConfigurationType, and it doesn't quite fit in
this newer typed API, e.g. isConfigurationFromContext() can receive a configuration
instance of a wrong type (DocutilsRunConfiguration for SphinxConfigurationProducer and
vice-versa) due to it, producing a CCE at runtime. I employed a workaround already
used in Python testing run configurations sharing the same problem. Namely,
overloaded getConfigurationSettingsList() to additionally check that instances of
RunnerAndConfigurationSettings with RestRunConfigurationType type actually
correspond to run configurations of the proper concrete class.

Note that setupConfigurationFromContext can also receive a run configuration of a wrong
type but in reality it doesn't happen since Sphinx and Docutils run configurations are
applied to different contexts -- directories and individual .rst files respectively.

GitOrigin-RevId: 15fbb90917edd68e6f29b696c527ff04d4eed433
This commit is contained in:
Mikhail Golubev
2020-04-28 13:22:25 +03:00
committed by intellij-monorepo-bot
parent 60703fb0e8
commit e1e70a2c7c
3 changed files with 65 additions and 89 deletions

View File

@@ -10,8 +10,8 @@
implementationClass="com.jetbrains.rest.inspections.RestRoleInspection"/>
<configurationType implementation="com.jetbrains.rest.run.RestRunConfigurationType"/>
<configurationProducer implementation="com.jetbrains.rest.run.docutils.DocutilsConfigurationProducer"/>
<configurationProducer implementation="com.jetbrains.rest.run.sphinx.SphinxConfigurationProducer"/>
<runConfigurationProducer implementation="com.jetbrains.rest.run.docutils.DocutilsConfigurationProducer"/>
<runConfigurationProducer implementation="com.jetbrains.rest.run.sphinx.SphinxConfigurationProducer"/>
<lang.substitutor language="TEXT" implementationClass="com.jetbrains.rest.RestLanguageSubstitutor"/>
<languageInjector implementation="com.jetbrains.rest.PyRestDocstringLanguageInjector"/>

View File

@@ -1,53 +1,44 @@
// 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.
// 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.rest.run.docutils;
import com.intellij.execution.Location;
import com.intellij.execution.RunManager;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.junit.RuntimeConfigurationProducer;
import com.intellij.execution.actions.LazyRunConfigurationProducer;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.rest.RestFileType;
import com.jetbrains.rest.run.RestRunConfiguration;
import com.jetbrains.rest.run.RestRunConfigurationType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* User : catherine
*/
public class DocutilsConfigurationProducer extends RuntimeConfigurationProducer implements Cloneable {
public DocutilsConfigurationProducer() {
super(RestRunConfigurationType.getInstance().DOCUTILS_FACTORY);
public class DocutilsConfigurationProducer extends LazyRunConfigurationProducer<DocutilsRunConfiguration> {
@NotNull
@Override
public ConfigurationFactory getConfigurationFactory() {
return RestRunConfigurationType.getInstance().DOCUTILS_FACTORY;
}
@Override
public PsiElement getSourceElement() {
return restoreSourceElement();
}
@Override
protected RunnerAndConfigurationSettings createConfigurationByElement(final Location location, final ConfigurationContext context) {
PsiFile script = location.getPsiElement().getContainingFile();
protected boolean setupConfigurationFromContext(@NotNull DocutilsRunConfiguration configuration,
@NotNull ConfigurationContext context,
@NotNull Ref<PsiElement> sourceElement) {
PsiFile script = sourceElement.get().getContainingFile();
if (script == null || script.getFileType() != RestFileType.INSTANCE) {
return null;
return false;
}
Module module = ModuleUtilCore.findModuleForPsiElement(script);
storeSourceElement(script);
final Project project = script.getProject();
RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context);
DocutilsRunConfiguration configuration = (DocutilsRunConfiguration) settings.getConfiguration();
final VirtualFile vFile = script.getVirtualFile();
if (vFile == null) return null;
if (vFile == null) return false;
configuration.setInputFile(vFile.getPath());
configuration.setName(script.getName());
@@ -61,8 +52,9 @@ public class DocutilsConfigurationProducer extends RuntimeConfigurationProducer
configuration.setOpenInBrowser(true);
}
if (configuration.getTask().isEmpty())
if (configuration.getTask().isEmpty()) {
configuration.setTask("rst2html");
}
final VirtualFile parent = vFile.getParent();
if (parent != null) {
configuration.setWorkingDirectory(parent.getPath());
@@ -72,34 +64,31 @@ public class DocutilsConfigurationProducer extends RuntimeConfigurationProducer
configuration.setUseModuleSdk(true);
configuration.setModule(module);
}
return settings;
return true;
}
@Nullable
@Override
protected RunnerAndConfigurationSettings findExistingByElement(Location location,
@NotNull List<? extends RunnerAndConfigurationSettings> existingConfigurations,
ConfigurationContext context) {
PsiFile script = location.getPsiElement().getContainingFile();
public boolean isConfigurationFromContext(@NotNull DocutilsRunConfiguration configuration, @NotNull ConfigurationContext context) {
final PsiElement element = context.getPsiLocation();
if (element == null) {
return false;
}
PsiFile script = element.getContainingFile();
if (script == null) {
return null;
return false;
}
final VirtualFile vFile = script.getVirtualFile();
if (vFile == null) {
return null;
return false;
}
String path = vFile.getPath();
for (RunnerAndConfigurationSettings configuration : existingConfigurations) {
final String scriptName = ((RestRunConfiguration)configuration.getConfiguration()).getInputFile();
if (FileUtil.toSystemIndependentName(scriptName).equals(FileUtil.toSystemIndependentName(path))) {
return configuration;
}
}
return null;
final String scriptName = configuration.getInputFile();
return FileUtil.toSystemIndependentName(scriptName).equals(FileUtil.toSystemIndependentName(path));
}
@Override
public int compareTo(final Object o) {
return PREFERED;
protected @NotNull List<RunnerAndConfigurationSettings> getConfigurationSettingsList(@NotNull RunManager runManager) {
return ContainerUtil.filter(super.getConfigurationSettingsList(runManager),
s -> s.getConfiguration() instanceof DocutilsRunConfiguration);
}
}

View File

@@ -1,65 +1,59 @@
// 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.
// 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.rest.run.sphinx;
import com.intellij.execution.Location;
import com.intellij.execution.RunManager;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.junit.RuntimeConfigurationProducer;
import com.intellij.execution.actions.LazyRunConfigurationProducer;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.rest.RestFile;
import com.jetbrains.rest.run.RestRunConfiguration;
import com.jetbrains.rest.run.RestRunConfigurationType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* User : catherine
*/
public class SphinxConfigurationProducer extends RuntimeConfigurationProducer implements Cloneable {
public SphinxConfigurationProducer() {
super(RestRunConfigurationType.getInstance().SPHINX_FACTORY);
public class SphinxConfigurationProducer extends LazyRunConfigurationProducer<SphinxRunConfiguration> {
@NotNull
@Override
public ConfigurationFactory getConfigurationFactory() {
return RestRunConfigurationType.getInstance().SPHINX_FACTORY;
}
@Override
public PsiElement getSourceElement() {
return restoreSourceElement();
}
protected boolean setupConfigurationFromContext(@NotNull SphinxRunConfiguration configuration,
@NotNull ConfigurationContext context,
@NotNull Ref<PsiElement> sourceElement) {
PsiElement element = sourceElement.get();
if (!(element instanceof PsiDirectory)) return false;
@Override
protected RunnerAndConfigurationSettings createConfigurationByElement(final Location location, final ConfigurationContext context) {
PsiElement element = location.getPsiElement();
if (!(element instanceof PsiDirectory)) return null;
storeSourceElement(element);
PsiDirectory directory = (PsiDirectory)element;
boolean hasRstFile = false;
boolean hasConf = false;
for (PsiFile file : directory.getFiles()) {
if ("conf.py".equals(file.getName()))
if ("conf.py".equals(file.getName())) {
hasConf = true;
}
if (file instanceof RestFile) {
hasRstFile = true;
}
}
if (!hasRstFile || !hasConf) return null;
final Project project = directory.getProject();
RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context);
SphinxRunConfiguration configuration = (SphinxRunConfiguration) settings.getConfiguration();
if (!hasRstFile || !hasConf) return false;
final VirtualFile vFile = directory.getVirtualFile();
configuration.setInputFile(vFile.getPath());
configuration.setName(((PsiDirectory)element).getName());
if (configuration.getTask().isEmpty())
if (configuration.getTask().isEmpty()) {
configuration.setTask("html");
}
final VirtualFile parent = vFile.getParent();
if (parent != null) {
configuration.setWorkingDirectory(parent.getPath());
@@ -70,29 +64,22 @@ public class SphinxConfigurationProducer extends RuntimeConfigurationProducer im
configuration.setUseModuleSdk(true);
configuration.setModule(module);
}
return settings;
return true;
}
@Nullable
@Override
protected RunnerAndConfigurationSettings findExistingByElement(Location location,
@NotNull List<? extends RunnerAndConfigurationSettings> existingConfigurations,
ConfigurationContext context) {
PsiElement element = location.getPsiElement();
if (!(element instanceof PsiDirectory)) return null;
public boolean isConfigurationFromContext(@NotNull SphinxRunConfiguration configuration, @NotNull ConfigurationContext context) {
PsiElement element = context.getPsiLocation();
if (!(element instanceof PsiDirectory)) return false;
final VirtualFile vFile = ((PsiDirectory)element).getVirtualFile();
String path = vFile.getPath();
for (RunnerAndConfigurationSettings configuration : existingConfigurations) {
final String scriptName = ((RestRunConfiguration)configuration.getConfiguration()).getInputFile();
if (FileUtil.toSystemIndependentName(scriptName).equals(FileUtil.toSystemIndependentName(path))) {
return configuration;
}
}
return null;
final String scriptName = configuration.getInputFile();
return FileUtil.toSystemIndependentName(scriptName).equals(FileUtil.toSystemIndependentName(path));
}
@Override
public int compareTo(final Object o) {
return PREFERED;
protected @NotNull List<RunnerAndConfigurationSettings> getConfigurationSettingsList(@NotNull RunManager runManager) {
return ContainerUtil.filter(super.getConfigurationSettingsList(runManager),
s -> s.getConfiguration() instanceof SphinxRunConfiguration);
}
}