org.gradle.plugins.ide.idea.internal.IdeaScalaConfigurer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gradle.plugins.ide.idea.internal;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import groovy.util.Node;
import org.gradle.BuildAdapter;
import org.gradle.api.Action;
import org.gradle.api.GradleScriptException;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.XmlProvider;
import org.gradle.api.file.FileCollection;
import org.gradle.api.invocation.Gradle;
import org.gradle.api.plugins.scala.ScalaBasePlugin;
import org.gradle.api.tasks.ScalaRuntime;
import org.gradle.language.scala.ScalaPlatform;
import org.gradle.language.scala.internal.DefaultScalaPlatform;
import org.gradle.language.scala.plugins.ScalaLanguagePlugin;
import org.gradle.plugins.ide.idea.IdeaPlugin;
import org.gradle.plugins.ide.idea.model.Dependency;
import org.gradle.plugins.ide.idea.model.FilePath;
import org.gradle.plugins.ide.idea.model.IdeaModel;
import org.gradle.plugins.ide.idea.model.IdeaModule;
import org.gradle.plugins.ide.idea.model.ModuleLibrary;
import org.gradle.plugins.ide.idea.model.ProjectLibrary;
import org.gradle.util.VersionNumber;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObject.findOrCreateFirstChildNamed;
import static org.gradle.plugins.ide.internal.generator.XmlPersistableConfigurationObject.findOrCreateFirstChildWithAttributeValue;
public class IdeaScalaConfigurer {
// More information: http://blog.jetbrains.com/scala/2014/10/30/scala-plugin-update-for-intellij-idea-14-rc-is-out/
private static final VersionNumber IDEA_VERSION_WHEN_SCALA_SDK_WAS_INTRODUCED = VersionNumber.version(14);
private final Project rootProject;
public IdeaScalaConfigurer(Project rootProject) {
this.rootProject = rootProject;
}
public void configure() {
rootProject.getGradle().addBuildListener(new BuildAdapter() {
public void projectsEvaluated(Gradle gradle) {
VersionNumber ideaTargetVersion = findIdeaTargetVersion();
final boolean useScalaSdk = ideaTargetVersion == null || IDEA_VERSION_WHEN_SCALA_SDK_WAS_INTRODUCED.compareTo(ideaTargetVersion) <= 0;
final Collection scalaProjects = findProjectsApplyingIdeaAndScalaPlugins();
final Map scalaCompilerLibraries = Maps.newHashMap();
rootProject.getTasks().getByName("ideaProject").doFirst(new Action() {
@Override
public void execute(Task task) {
if (scalaProjects.size() > 0) {
scalaCompilerLibraries.clear();
scalaCompilerLibraries.putAll(resolveScalaCompilerLibraries(scalaProjects, useScalaSdk));
declareUniqueProjectLibraries(Sets.newLinkedHashSet(scalaCompilerLibraries.values()));
}
}
});
rootProject.configure(scalaProjects, new Action() {
@Override
public void execute(final Project project) {
project.getExtensions().getByType(IdeaModel.class).getModule().getIml().withXml(new Action() {
@Override
public void execute(XmlProvider xmlProvider) {
if (useScalaSdk) {
declareScalaSdk(scalaCompilerLibraries.get(project.getPath()), xmlProvider.asNode());
} else {
declareScalaFacet(scalaCompilerLibraries.get(project.getPath()), xmlProvider.asNode());
}
}
});
}
});
}
});
}
private static Map resolveScalaCompilerLibraries(Collection scalaProjects, boolean useScalaSdk) {
Map scalaCompilerLibraries = Maps.newHashMap();
for (Project scalaProject : scalaProjects) {
IdeaModule ideaModule = scalaProject.getExtensions().getByType(IdeaModel.class).getModule();
Iterable files = getIdeaModuleLibraryDependenciesAsFiles(ideaModule);
ProjectLibrary library = createScalaSdkLibrary(scalaProject, files, useScalaSdk, ideaModule);
if (library != null) {
ProjectLibrary duplicate = Iterables.find(scalaCompilerLibraries.values(), Predicates.equalTo(library), null);
scalaCompilerLibraries.put(scalaProject.getPath(), duplicate == null ? library : duplicate);
}
}
return scalaCompilerLibraries;
}
private static Iterable getIdeaModuleLibraryDependenciesAsFiles(IdeaModule ideaModule) {
// could make resolveDependencies() cache its result for later use by GenerateIdeaModule
Set dependencies = ideaModule.resolveDependencies();
List files = Lists.newArrayList();
for(ModuleLibrary moduleLibrary : Iterables.filter(dependencies, ModuleLibrary.class)) {
for (FilePath filePath : Iterables.filter(moduleLibrary.getClasses(), FilePath.class)) {
files.add(filePath.getFile());
}
}
return files;
}
private static ProjectLibrary createScalaSdkLibrary(Project scalaProject, Iterable files, boolean useScalaSdk, IdeaModule ideaModule) {
ScalaRuntime runtime = scalaProject.getExtensions().findByType(ScalaRuntime.class);
if (runtime != null) {
// Old Scala Plugin does not specify a ScalaPlatform
FileCollection scalaClasspath = runtime.inferScalaClasspath(files);
File compilerJar = runtime.findScalaJar(scalaClasspath, "compiler");
ScalaPlatform scalaPlatform = compilerJar != null ? new DefaultScalaPlatform(runtime.getScalaVersion(compilerJar)) : new DefaultScalaPlatform();
return createScalaSdkFromPlatform(scalaPlatform, scalaClasspath, useScalaSdk);
} else if (ideaModule.getScalaPlatform() != null) {
// TODO: Wrong, using the full classpath of the application
return createScalaSdkFromPlatform(ideaModule.getScalaPlatform(), scalaProject.files(files), useScalaSdk);
} else {
// One of the Scala plugins is applied, but ScalaRuntime extension is missing or the ScalaPlatform is undefined.
// we can't create a Scala SDK without either one
return null;
}
}
private static ProjectLibrary createScalaSdkFromPlatform(ScalaPlatform platform, FileCollection scalaClasspath, boolean useScalaSdk) {
String version = platform.getScalaVersion();
if (useScalaSdk) {
return createScalaSdkLibrary("scala-sdk-" + version, scalaClasspath);
}
return createProjectLibrary("scala-compiler-" + version, scalaClasspath);
}
private void declareUniqueProjectLibraries(Set projectLibraries) {
Set existingLibraries = rootProject.getExtensions().getByType(IdeaModel.class).getProject().getProjectLibraries();
Set newLibraries = Sets.difference(projectLibraries, existingLibraries);
for (ProjectLibrary newLibrary : newLibraries) {
String originalName = newLibrary.getName();
int suffix = 1;
while (containsLibraryWithSameName(existingLibraries, newLibrary.getName())) {
newLibrary.setName(originalName + "-" + (suffix++));
}
existingLibraries.add(newLibrary);
}
}
private static boolean containsLibraryWithSameName(Set libraries, final String name) {
return Iterables.any(libraries, new Predicate() {
@Override
public boolean apply(ProjectLibrary library) {
return Objects.equal(library.getName(), name);
}
});
}
private static void declareScalaSdk(ProjectLibrary scalaSdkLibrary, Node iml) {
// only define a Scala SDK for a module if we could create a scalaSdkLibrary
if (scalaSdkLibrary != null) {
Node newModuleRootManager = findOrCreateFirstChildWithAttributeValue(iml, "component", "name", "NewModuleRootManager");
Node sdkLibrary = findOrCreateFirstChildWithAttributeValue(newModuleRootManager, "orderEntry", "name", scalaSdkLibrary.getName());
sdkLibrary.attributes().put("type", "library");
sdkLibrary.attributes().put("level", "project");
}
}
private static void declareScalaFacet(ProjectLibrary scalaCompilerLibrary, Node iml) {
Node facetManager = findOrCreateFirstChildWithAttributeValue(iml, "component", "name", "FacetManager");
Node scalaFacet = findOrCreateFirstChildWithAttributeValue(facetManager, "facet", "type", "scala");
scalaFacet.attributes().put("name", "Scala");
Node configuration = findOrCreateFirstChildNamed(scalaFacet, "configuration");
Node libraryLevel = findOrCreateFirstChildWithAttributeValue(configuration, "option", "name", "compilerLibraryLevel");
libraryLevel.attributes().put("value", "Project");
Node libraryName = findOrCreateFirstChildWithAttributeValue(configuration, "option", "name", "compilerLibraryName");
libraryName.attributes().put("value", scalaCompilerLibrary.getName());
}
private Collection findProjectsApplyingIdeaAndScalaPlugins() {
return Collections2.filter(rootProject.getAllprojects(), new Predicate() {
@Override
public boolean apply(Project project) {
return project.getPlugins().hasPlugin(IdeaPlugin.class) && (project.getPlugins().hasPlugin(ScalaBasePlugin.class) || project.getPlugins().hasPlugin(ScalaLanguagePlugin.class));
}
});
}
private VersionNumber findIdeaTargetVersion() {
VersionNumber targetVersion = null;
String targetVersionString = rootProject.getExtensions().getByType(IdeaModel.class).getTargetVersion();
if (targetVersionString != null) {
targetVersion = VersionNumber.parse(targetVersionString);
if (targetVersion.equals(VersionNumber.UNKNOWN)) {
throw new GradleScriptException("String \'" + targetVersionString + "\' is not a valid value for IdeaModel.targetVersion.", null);
}
}
return targetVersion;
}
private static ProjectLibrary createProjectLibrary(String name, Iterable jars) {
ProjectLibrary projectLibrary = new ProjectLibrary();
projectLibrary.setName(name);
projectLibrary.setClasses(Sets.newLinkedHashSet(jars));
return projectLibrary;
}
private static ProjectLibrary createScalaSdkLibrary(String name, Iterable jars) {
ProjectLibrary projectLibrary = new ProjectLibrary();
projectLibrary.setName(name);
projectLibrary.setType("Scala");
projectLibrary.setCompilerClasspath(Sets.newLinkedHashSet(jars));
return projectLibrary;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy