// Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).
package com.twitter.intellij.pants.service.scala;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ProjectKeys;
import com.intellij.openapi.externalSystem.model.project.LibraryData;
import com.intellij.openapi.externalSystem.model.project.LibraryDependencyData;
import com.intellij.openapi.externalSystem.model.project.LibraryLevel;
import com.intellij.openapi.externalSystem.model.project.LibraryPathType;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import com.twitter.intellij.pants.service.PantsCompileOptionsExecutor;
import com.twitter.intellij.pants.service.project.model.graph.BuildGraph;
import com.twitter.intellij.pants.service.project.PantsResolverExtension;
import com.twitter.intellij.pants.service.project.model.LibraryInfo;
import com.twitter.intellij.pants.service.project.model.ProjectInfo;
import com.twitter.intellij.pants.service.project.model.TargetInfo;
import com.twitter.intellij.pants.util.PantsConstants;
import com.twitter.intellij.pants.util.PantsScalaUtil;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class ScalaSdkResolver implements PantsResolverExtension {
private static final Logger LOG = Logger.getInstance(ScalaSdkResolver.class);
@Override
public void resolve(
@NotNull ProjectInfo projectInfo,
@NotNull PantsCompileOptionsExecutor executor,
@NotNull DataNode<ProjectData> projectDataNode,
@NotNull Map<String, DataNode<ModuleData>> modules,
@NotNull Optional<BuildGraph> buildGraph
) {
final Map<String, Set<String>> scalaLibId2Jars = new HashMap<String, Set<String>>();
for (String libId : ContainerUtil.sorted(projectInfo.getLibraries().keySet())) {
if (PantsScalaUtil.isScalaLibraryLib(libId)) {
final LibraryInfo scalaLib = projectInfo.getLibraries(libId);
final String scalaLibPath = scalaLib != null ? scalaLib.getDefault() : null;
if (scalaLibPath == null) {
continue;
}
final Set<String> scalaSdkJars = new HashSet<String>();
for (String scalaLibNameToAdd : PantsScalaUtil.getScalaLibNamesToAdd()) {
findAndAddScalaLib(scalaSdkJars, scalaLibPath, scalaLibNameToAdd);
}
scalaLibId2Jars.put(libId, scalaSdkJars);
}
}
final String defaultScalaLibId = ContainerUtil.getFirstItem(scalaLibId2Jars.keySet());
if (defaultScalaLibId == null) {
LOG.debug("Didn't find any Scala libraries");
// no scala libs - no problems
return;
}
final Map<String, LibraryData> scalaLibId2Data = new HashMap<String, LibraryData>();
for (Map.Entry<String, Set<String>> entry : scalaLibId2Jars.entrySet()) {
final String scalaLibraryId = entry.getKey();
final Set<String> scalaJars = entry.getValue();
final LibraryData libraryData =
new LibraryData(PantsConstants.SYSTEM_ID, scalaLibraryId);
for (String jarPath : scalaJars) {
// todo: sources + docs
libraryData.addPath(LibraryPathType.BINARY, jarPath);
}
projectDataNode.createChild(ProjectKeys.LIBRARY, libraryData);
scalaLibId2Data.put(scalaLibraryId, libraryData);
}
for (Map.Entry<String, TargetInfo> entry : projectInfo.getTargets().entrySet()) {
final String mainTarget = entry.getKey();
final DataNode<ModuleData> moduleDataNode = modules.get(mainTarget);
final TargetInfo targetInfo = entry.getValue();
if (moduleDataNode != null && targetInfo.isScalaTarget()) {
String scalaLibId = StringUtil.notNullize(targetInfo.findScalaLibId(), defaultScalaLibId);
LibraryData libraryData = scalaLibId2Data.get(scalaLibId);
if (libraryData == null) {
LOG.warn("Can't find Scala SDK for " + scalaLibId);
final Map.Entry<String, LibraryData> libraryDataEntry = scalaLibId2Data.entrySet().iterator().next();
scalaLibId = libraryDataEntry.getKey();
libraryData = libraryDataEntry.getValue();
}
final LibraryDependencyData libraryDependencyData = new LibraryDependencyData(moduleDataNode.getData(), libraryData, LibraryLevel.PROJECT);
moduleDataNode.createChild(ProjectKeys.LIBRARY_DEPENDENCY, libraryDependencyData);
final ScalaModelData scalaModelData = new ScalaModelData(scalaLibId, libraryData.getPaths(LibraryPathType.BINARY));
moduleDataNode.createChild(ScalaModelData.KEY, scalaModelData);
}
}
}
private void findAndAddScalaLib(Set<String> files, String jarPath, String libName) {
final File libFile = PantsScalaUtil.getScalaLibFile(jarPath, libName);
if (libFile.exists()) {
files.add(libFile.getAbsolutePath());
} else {
LOG.warn("Could not find scala library path: " + libFile);
}
}
}