// Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).
package com.twitter.intellij.pants.service.python;
import com.intellij.facet.FacetManager;
import com.intellij.facet.ModifiableFacetModel;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.Key;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataService;
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.util.Computable;
import com.intellij.util.Function;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.jetbrains.python.facet.PythonFacet;
import com.jetbrains.python.facet.PythonFacetType;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.testing.TestRunnerService;
import com.twitter.intellij.pants.service.project.model.PythonInterpreterInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
public class PantsPythonSetupDataService implements ProjectDataService<PythonSetupData, Module> {
@NotNull
@Override
public Key<PythonSetupData> getTargetDataKey() {
return PythonSetupData.KEY;
}
@Override
public void importData(
@NotNull final Collection<DataNode<PythonSetupData>> toImport,
@Nullable ProjectData projectData,
@NotNull Project project,
@NotNull final IdeModifiableModelsProvider modelsProvider
) {
final Set<PythonInterpreterInfo> interpreters = ContainerUtil.map2Set(
toImport,
new Function<DataNode<PythonSetupData>, PythonInterpreterInfo>() {
@Override
public PythonInterpreterInfo fun(DataNode<PythonSetupData> node) {
return node.getData().getInterpreterInfo();
}
}
);
if (interpreters.isEmpty()) {
return;
}
final Map<PythonInterpreterInfo, Sdk> interpreter2sdk = ContainerUtilRt.newHashMap();
ExternalSystemApiUtil.executeProjectChangeAction(false, new DisposeAwareProjectChange(project) {
@Override
public void execute() {
for (final PythonInterpreterInfo interpreterInfo : interpreters) {
//final String binFolder = PathUtil.getParentPath(interpreter);
//final String interpreterHome = PathUtil.getParentPath(binFolder);
final String interpreter = interpreterInfo.getBinary();
Sdk pythonSdk = PythonSdkType.findSdkByPath(interpreter);
if (pythonSdk == null) {
final ProjectJdkTable jdkTable = ProjectJdkTable.getInstance();
pythonSdk = jdkTable.createSdk(PathUtil.getFileName(interpreter), PythonSdkType.getInstance());
jdkTable.addJdk(pythonSdk);
final SdkModificator modificator = pythonSdk.getSdkModificator();
modificator.setHomePath(interpreter);
modificator.commitChanges();
PythonSdkType.getInstance().setupSdkPaths(pythonSdk);
}
interpreter2sdk.put(interpreterInfo, pythonSdk);
}
}
});
for (DataNode<PythonSetupData> dataNode : toImport) {
final PythonSetupData pythonSetupData = dataNode.getData();
final Sdk pythonSdk = interpreter2sdk.get(pythonSetupData.getInterpreterInfo());
final Module module = modelsProvider.findIdeModule(pythonSetupData.getOwnerModuleData());
if (module == null) {
return;
}
FacetManager facetManager = FacetManager.getInstance(module);
PythonFacet facet = facetManager.getFacetByType(PythonFacetType.getInstance().getId());
if (facet == null) {
facet = facetManager.createFacet(PythonFacetType.getInstance(), "Python", null);
facet.getConfiguration().setSdk(pythonSdk);
final ModifiableFacetModel facetModel = modelsProvider.getModifiableFacetModel(module);
facetModel.addFacet(facet);
TestRunnerService.getInstance(module).setProjectConfiguration("py.test");
}
}
}
@NotNull
@Override
public Computable<Collection<Module>> computeOrphanData(
@NotNull Collection<DataNode<PythonSetupData>> toImport,
@NotNull ProjectData projectData,
@NotNull Project project,
@NotNull IdeModifiableModelsProvider modelsProvider
) {
return new Computable<Collection<Module>>() {
@Override
public Collection<Module> compute() {
return Collections.emptyList();
}
};
}
@Override
public void removeData(
@NotNull Computable<Collection<Module>> toRemove,
@NotNull Collection<DataNode<PythonSetupData>> toIgnore,
@NotNull ProjectData projectData,
@NotNull Project project,
@NotNull IdeModifiableModelsProvider modelsProvider
) {
}
}