Index: src/main/groovy/org/gradle/api/plugins/scala/ScalaPluginConvention.groovy =================================================================== --- src/main/groovy/org/gradle/api/plugins/scala/ScalaPluginConvention.groovy Tue Nov 04 21:23:02 EST 2008 +++ src/main/groovy/org/gradle/api/plugins/scala/ScalaPluginConvention.groovy Tue Nov 04 21:23:02 EST 2008 @@ -0,0 +1,39 @@ +package org.gradle.api.plugins.scala + +import org.gradle.api.Project +import org.gradle.api.internal.plugins.PluginUtil +import org.gradle.api.plugins.JavaPluginConvention + +class ScalaPluginConvention { + final Project project + List scalaSrcDirNames = [] + List scalaTestSrcDirNames = [] + List floatingScalaSrcDirs = [] + List floatingScalaTestSrcDirs = [] + String scalaDocDirName + + ScalaPluginConvention(Project project, Map customValues) { + this.project = project + scalaSrcDirNames << 'main/scala' + scalaTestSrcDirNames << 'test/scala' + scalaDocDirName = 'scaladoc' + PluginUtil.applyCustomValues(project.convention, this, customValues) + } + + List getScalaSrcDirs() { + scalaSrcDirNames.collect {new File(javaConvention.srcRoot, it)} + floatingScalaSrcDirs + } + + List getScalaTestSrcDirs() { + scalaTestSrcDirNames.collect {new File(javaConvention.srcRoot, it)} + floatingScalaTestSrcDirs + } + + File getScalaDocDir() { + return new File(javaConvention.docsDir, scalaDocDirName) + } + + private JavaPluginConvention getJavaConvention() { + project.convention.plugins.java + } + +} Index: src/main/groovy/org/gradle/api/plugins/scala/ScalaCompileOptions.groovy =================================================================== --- src/main/groovy/org/gradle/api/plugins/scala/ScalaCompileOptions.groovy Tue Nov 04 21:23:02 EST 2008 +++ src/main/groovy/org/gradle/api/plugins/scala/ScalaCompileOptions.groovy Tue Nov 04 21:23:02 EST 2008 @@ -0,0 +1,124 @@ +package org.gradle.api.plugins.scala + +import org.gradle.api.tasks.compile.AbstractOptions + +class ScalaCompileOptions extends AbstractOptions { + /** + * Whether to use the fsc compile daemon. + */ + boolean useCompileDaemon = false + + // NOTE: Does not work for scalac 2.7.1 due to a bug in the ant task + /** + * Server (host:port) on which the compile daemon is running. + * The host must share disk access with the client process. + * If not specified, launches the daemon on the localhost. + * This parameter can only be specified if useCompileDaemon is true. + */ + String daemonServer; + + /** + * Fail the build on compilation errors. + */ + boolean failOnError = true + + /** + * Generate deprecation information. + */ + boolean deprecation = true + + /** + * Generate unchecked information. + */ + boolean unchecked = true + + /** + * Generate debugging information. + * Legal values: none, source, line, vars, notailcalls + */ + String debugLevel + + /** + * Run optimisations. + */ + boolean optimize = false + + /** + * Encoding of source files. + */ + String encoding = null + + /** + * Whether to force the compilation of all files. + * Legal values: + * - never (only compile modified files) + * - changed (compile all files when at least one file is modified) + * - always (always recompile all files) + */ + String force = "never" + + /** + * Specifies which backend to use. + * Legal values: 1.4, 1.5 + */ + String targetCompatibility = '1.5' + + /** + * Additional parameters passed to the compiler. + * Each parameter must start with '-'. + */ + List additionalParameters + + /** + * List files to be compiled. + */ + boolean listFiles + + /** + * Specifies the amount of logging. + * Legal values: none, verbose, debug + */ + String loggingLevel + + /** + * Phases of the compiler to log. + * Legal values: namer, typer, pickler, uncurry, tailcalls, transmatch, explicitouter, erasure, + * lambdalift, flatten, constructors, mixin, icode, jvm, terminal. + */ + List loggingPhases + + + Map fieldName2AntMap() { + [ + failOnError: 'failonerror', + loggingLevel: 'logging', + loggingPhases: 'logPhase', + targetCompatibility: 'target', + optimize: 'optimise', + daemonServer: 'server', + listFiles: 'scalacDebugging', + debugLevel: 'debugInfo', + additionalParameters: 'addParams' + ] + } + + Map fieldValue2AntMap() { + [ + deprecation: {toBooleanString(deprecation)}, + unchecked: {toBooleanString(unchecked)}, + optimize: {toBooleanString(optimize)}, + targetCompatibility: {"jvm-${targetCompatibility}"}, + loggingPhases: {loggingPhases.isEmpty() ? ' ' : loggingPhases.join(',')}, + additionalParameters: {additionalParameters.isEmpty() ? ' ' : additionalParameters.join(' ')}, + ] + } + + List excludedFieldsFromOptionMap() { + ['useCompileDaemon'] + } + + private String toBooleanString(value) { + return value ? 'on' : 'off' + } + +} Index: src/toplevel/plugin.properties =================================================================== --- src/toplevel/plugin.properties (revision 1083) +++ src/toplevel/plugin.properties Tue Nov 04 18:55:35 EST 2008 @@ -1,3 +1,4 @@ java=org.gradle.api.plugins.JavaPlugin groovy=org.gradle.api.plugins.GroovyPlugin -war=org.gradle.api.plugins.WarPlugin \ No newline at end of file +war=org.gradle.api.plugins.WarPlugin +scala=org.gradle.api.plugins.scala.ScalaPlugin Index: src/test/groovy/org/gradle/api/plugins/scala/ScalaPluginTest.groovy =================================================================== --- src/test/groovy/org/gradle/api/plugins/scala/ScalaPluginTest.groovy Tue Nov 04 21:46:13 EST 2008 +++ src/test/groovy/org/gradle/api/plugins/scala/ScalaPluginTest.groovy Tue Nov 04 21:46:13 EST 2008 @@ -0,0 +1,44 @@ +package org.gradle.api.plugins.scala + +import org.gradle.api.Project +import org.gradle.api.internal.project.PluginRegistry +import org.gradle.api.plugins.JavaPlugin +import org.gradle.util.HelperUtil +import static org.gradle.util.WrapUtil.toSet +import static org.hamcrest.Matchers.* +import static org.junit.Assert.assertFalse +import static org.junit.Assert.assertThat +import org.junit.Test + +public class ScalaPluginTest { + + @Test + public void testApply() { + Project project = HelperUtil.createRootProject(new File('path', 'root')) + ScalaPlugin scalaPlugin = new ScalaPlugin() + scalaPlugin.apply(project, new PluginRegistry()) + + def configuration = project.dependencies.configurations[JavaPlugin.COMPILE] + assertFalse(configuration.visible) + assertFalse(configuration.transitive) + + configuration = project.dependencies.configurations[ScalaPlugin.SCALA_TOOLS] + assertThat(configuration.extendsFrom, equalTo(toSet())) + assertFalse(configuration.visible) + assertFalse(configuration.transitive) + + def task = project.tasks[JavaPlugin.COMPILE] + assertThat(task, instanceOf(ScalaCompile.class)) + assertThat(task.srcDirs, hasItems(project.convention.plugins.java.srcDirs as Object[])) + assertThat(task.scalaSourceDirs, hasItems(project.convention.plugins.scala.scalaSrcDirs as Object[])) + + task = project.tasks[JavaPlugin.TEST_COMPILE] + assertThat(task, instanceOf(ScalaCompile.class)) + assertThat(task.srcDirs, hasItems(project.convention.plugins.java.testSrcDirs as Object[])) + assertThat(task.scalaSourceDirs, hasItems(project.convention.plugins.scala.scalaTestSrcDirs as Object[])) + + task = project.tasks[ScalaPlugin.SCALA_DOC_TASK] + assertThat(task, instanceOf(ScalaDoc.class)) + assertThat(task.destinationDir, equalTo(project.convention.plugins.scala.scalaDocDir)) + } +} Index: src/samples/scalaproject/settings.gradle =================================================================== --- src/samples/scalaproject/settings.gradle Tue Nov 04 18:53:02 EST 2008 +++ src/samples/scalaproject/settings.gradle Tue Nov 04 18:53:02 EST 2008 @@ -0,0 +1,1 @@ +include "api" Index: src/main/groovy/org/gradle/api/plugins/scala/ScalaDefine.java =================================================================== --- src/main/groovy/org/gradle/api/plugins/scala/ScalaDefine.java Tue Nov 04 20:20:11 EST 2008 +++ src/main/groovy/org/gradle/api/plugins/scala/ScalaDefine.java Tue Nov 04 20:20:11 EST 2008 @@ -0,0 +1,69 @@ +package org.gradle.api.plugins.scala; + +import org.gradle.api.DependencyManager; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.TaskAction; +import org.gradle.api.internal.ConventionTask; + +import java.io.File; +import java.util.List; + +public class ScalaDefine extends ConventionTask { + + private DependencyManager dependencyManager; + + private AntScalaDefine antScalaDefine; + + public ScalaDefine(Project project, String name) { + super(project, name); + doFirst(new TaskAction() { + public void execute(Task task) { + defineAntTasks(task); + } + }); + } + + public AntScalaDefine getAntScalaDefine() { + if (antScalaDefine == null) { + antScalaDefine = new AntScalaDefine(getAnt(), getClasspath()); + } + return antScalaDefine; + } + + public void setAntScalaDefine(AntScalaDefine antScalaDefine) { + this.antScalaDefine = antScalaDefine; + } + + /** + *

Returns the classpath used to define the Scala ant tasks.

+ * + * @return The list of files containing scala tools libraries. + */ + public List getClasspath() { + return getDependencyManager().resolveTask(getName()); + } + + /** + *

Returns the {@link DependencyManager} which this task uses to resolve the classpath + * to define the scala ant tasks.

+ * + * @return The dependency manager. + */ + public DependencyManager getDependencyManager() { + return (DependencyManager) conv(dependencyManager, "dependencyManager"); + } + + /** + *

Sets the {@link DependencyManager} which this task uses to resolve the classpath + * to define the scala ant tasks.

+ */ + public void setDependencyManager(DependencyManager dependencyManager) { + this.dependencyManager = dependencyManager; + } + + protected void defineAntTasks(Task task) { + getAntScalaDefine().execute(); + } + +} Index: src/test/groovy/org/gradle/api/plugins/scala/ScalaPluginConventionTest.groovy =================================================================== --- src/test/groovy/org/gradle/api/plugins/scala/ScalaPluginConventionTest.groovy Tue Nov 04 21:46:13 EST 2008 +++ src/test/groovy/org/gradle/api/plugins/scala/ScalaPluginConventionTest.groovy Tue Nov 04 21:46:13 EST 2008 @@ -0,0 +1,65 @@ +package org.gradle.api.plugins.scala + +import org.gradle.api.plugins.AbstractPluginConventionTest +import org.gradle.api.plugins.JavaPluginConvention +import static org.hamcrest.Matchers.equalTo +import static org.junit.Assert.assertEquals +import static org.junit.Assert.assertThat +import org.junit.Before +import org.junit.Test + +public class ScalaPluginConventionTest extends AbstractPluginConventionTest { + private ScalaPluginConvention scalaConvention + private JavaPluginConvention javaConvention + + Class getType() { + ScalaPluginConvention + } + + Map getCustomValues() { + [scalaSrcDirNames: ['newSourceRootName']] + } + + @Before public void setUp() { + super.setUp() + javaConvention = new JavaPluginConvention(project, [:]) + project.convention.plugins.java = javaConvention + scalaConvention = new ScalaPluginConvention(project, [:]) + } + + @Test public void testScalaConvention() { + assertEquals(['main/scala'], scalaConvention.scalaSrcDirNames) + assertEquals(['test/scala'], scalaConvention.scalaTestSrcDirNames) + assertEquals([], scalaConvention.floatingScalaSrcDirs) + assertEquals([], scalaConvention.floatingScalaTestSrcDirs) + } + + @Test + public void testScalaDefaultDirs() { + checkScalaDirs(project.srcRootName) + } + + @Test + public void testScalaDynamicDirs() { + project.srcRootName = 'mysrc' + project.buildDirName = 'mybuild' + checkScalaDirs(project.srcRootName) + } + + @Test + public void testScalaDocDirUsesJavaConventionToDetermineDocsDir() { + assertThat(scalaConvention.scalaDocDir, equalTo(new File(javaConvention.docsDir, "scaladoc"))) + + scalaConvention.scalaDocDirName = "other-dir" + assertThat(scalaConvention.scalaDocDir, equalTo(new File(javaConvention.docsDir, "other-dir"))) + } + + private void checkScalaDirs(String srcRootName) { + scalaConvention.floatingScalaSrcDirs << 'someScalaSrcDir' as File + scalaConvention.floatingScalaTestSrcDirs << 'someScalaTestSrcDir' as File + assertEquals([new File(project.srcRoot, scalaConvention.scalaSrcDirNames[0])] + scalaConvention.floatingScalaSrcDirs, + scalaConvention.scalaSrcDirs) + assertEquals([new File(project.srcRoot, scalaConvention.scalaTestSrcDirNames[0])] + scalaConvention.floatingScalaTestSrcDirs, + scalaConvention.scalaTestSrcDirs) + } +} Index: src/main/groovy/org/gradle/api/plugins/scala/AntScalaDefine.groovy =================================================================== --- src/main/groovy/org/gradle/api/plugins/scala/AntScalaDefine.groovy Tue Nov 04 21:23:02 EST 2008 +++ src/main/groovy/org/gradle/api/plugins/scala/AntScalaDefine.groovy Tue Nov 04 21:23:02 EST 2008 @@ -0,0 +1,29 @@ +package org.gradle.api.plugins.scala + +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +public class AntScalaDefine { + private static Logger logger = LoggerFactory.getLogger(AntScalaDefine) + + private final AntBuilder ant + private final List scalaToolsClasspath + + def AntScalaDefine(AntBuilder ant, List scalaToolsClasspath) { + this.ant = ant + this.scalaToolsClasspath = scalaToolsClasspath + } + + void execute() { + if (logger.isInfoEnabled()) { + logger.info("Defining Scala ant tasks with classpath ${scalaToolsClasspath}\n") + } + + ant.taskdef(resource: 'scala/tools/ant/antlib.xml', loaderRef: 'scala') { + scalaToolsClasspath.each {file -> + classpath(location: file) + } + } + } + +} Index: src/main/groovy/org/gradle/api/plugins/scala/AntScalaDoc.groovy =================================================================== --- src/main/groovy/org/gradle/api/plugins/scala/AntScalaDoc.groovy Tue Nov 04 21:23:02 EST 2008 +++ src/main/groovy/org/gradle/api/plugins/scala/AntScalaDoc.groovy Tue Nov 04 21:23:02 EST 2008 @@ -0,0 +1,73 @@ +package org.gradle.api.plugins.scala + +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +class AntScalaDoc { + private static Logger logger = LoggerFactory.getLogger(AntScalaDoc) + + private final AntBuilder ant + private final List bootclasspathFiles + private final List extensionDirs + + def AntScalaDoc(AntBuilder ant) { + this.ant = ant + this.bootclasspathFiles = [] + this.extensionDirs = [] + } + + def AntScalaDoc(AntBuilder ant, List bootclasspathFiles, List extensionDirs) { + this.ant = ant + this.bootclasspathFiles = bootclasspathFiles + this.extensionDirs = extensionDirs + } + + void execute(List sourceDirs, List includes, List excludes, File targetDir, + List classpathFiles, ScalaDocOptions docOptions) { + + ant.mkdir(dir: targetDir.absolutePath) + + Map options = ['destDir': targetDir] + docOptions.optionMap() + if (logger.isInfoEnabled()) { + StringBuilder builder = new StringBuilder() + builder.append("Generating Scaladoc from source ${sourceDirs}\n") + builder.append(" options = ${options}\n") + builder.append(" classpath = ${classpathFiles}\n") + if (includes) { + builder.append(" includes = ${includes}\n") + } + if (excludes) { + builder.append(" excludes = ${excludes}\n") + } + if (bootclasspathFiles) { + builder.append(" bootclasspath = ${bootclasspathFiles}\n") + } + if (extensionDirs) { + builder.append(" extDirs = ${extensionDirs}\n") + } + logger.info(builder.toString()) + } + + ant.scaladoc(options) { + sourceDirs.each {dir -> + src(location: dir) + } + bootclasspathFiles.each {file -> + bootclasspath(location: file) + } + extensionDirs.each {dir -> + extdirs(location: dir) + } + classpathFiles.each {file -> + classpath(location: file) + } + includes.each {pattern -> + include(name: pattern) + } + excludes.each {pattern -> + exclude(name: pattern) + } + } + } + +} Index: src/main/groovy/org/gradle/api/plugins/scala/AntScalaCompile.groovy =================================================================== --- src/main/groovy/org/gradle/api/plugins/scala/AntScalaCompile.groovy Tue Nov 04 21:23:02 EST 2008 +++ src/main/groovy/org/gradle/api/plugins/scala/AntScalaCompile.groovy Tue Nov 04 21:23:02 EST 2008 @@ -0,0 +1,74 @@ +package org.gradle.api.plugins.scala + +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +class AntScalaCompile { + private static Logger logger = LoggerFactory.getLogger(AntScalaCompile) + + private final AntBuilder ant + private final List bootclasspathFiles + private final List extensionDirs + + def AntScalaCompile(AntBuilder ant) { + this.ant = ant + this.bootclasspathFiles = [] + this.extensionDirs = [] + } + + def AntScalaCompile(AntBuilder ant, List bootclasspathFiles, List extensionDirs) { + this.ant = ant + this.bootclasspathFiles = bootclasspathFiles + this.extensionDirs = extensionDirs + } + + void execute(List sourceDirs, List includes, List excludes, File targetDir, + List classpathFiles, ScalaCompileOptions compileOptions) { + + ant.mkdir(dir: targetDir.absolutePath) + + Map options = ['destDir': targetDir] + compileOptions.optionMap() + String taskName = compileOptions.useCompileDaemon ? 'fsc' : 'scalac' + if (logger.isInfoEnabled()) { + StringBuilder builder = new StringBuilder() + builder.append("Compiling Scala with ${taskName} from source ${sourceDirs}\n") + builder.append(" options = ${options}\n") + builder.append(" classpath = ${classpathFiles}\n") + if (includes) { + builder.append(" includes = ${includes}\n") + } + if (excludes) { + builder.append(" excludes = ${excludes}\n") + } + if (bootclasspathFiles) { + builder.append(" bootclasspath = ${bootclasspathFiles}\n") + } + if (extensionDirs) { + builder.append(" extDirs = ${extensionDirs}\n") + } + logger.info(builder.toString()) + } + + ant."${taskName}"(options) { + sourceDirs.each {dir -> + src(location: dir) + } + bootclasspathFiles.each {file -> + bootclasspath(location: file) + } + extensionDirs.each {dir -> + extdirs(location: dir) + } + classpathFiles.each {file -> + classpath(location: file) + } + includes.each {pattern -> + include(name: pattern) + } + excludes.each {pattern -> + exclude(name: pattern) + } + } + } + +} Index: src/samples/scalaproject/build.gradle =================================================================== --- src/samples/scalaproject/build.gradle Tue Nov 04 21:52:56 EST 2008 +++ src/samples/scalaproject/build.gradle Tue Nov 04 21:52:56 EST 2008 @@ -0,0 +1,8 @@ +project.group = 'org.gradle' +project.version = '1.0' + +subprojects { + dependencies { + addFlatDirResolver('lib', "$rootDir/lib") + } +} Index: src/main/groovy/org/gradle/api/plugins/scala/ScalaCompile.java =================================================================== --- src/main/groovy/org/gradle/api/plugins/scala/ScalaCompile.java Tue Nov 04 21:23:02 EST 2008 +++ src/main/groovy/org/gradle/api/plugins/scala/ScalaCompile.java Tue Nov 04 21:23:02 EST 2008 @@ -0,0 +1,107 @@ +package org.gradle.api.plugins.scala; + +import org.gradle.api.InvalidUserDataException; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.TaskAction; +import org.gradle.api.tasks.compile.Compile; +import org.gradle.util.GUtil; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Task to perform scala compilation. + */ +public class ScalaCompile extends Compile { + + /** + * Directories containing scala source files. + */ + private List scalaSourceDirs; + + /** + * Include pattern for which scala files should be compiled (e.g. '**F;org/gradle/package1/')). + * This pattern is added as an nested include the scalac task. + */ + private List scalaIncludes; + + /** + * Exclude pattern for which files should be compiled (e.g. '**F;org/gradle/package2/A*.java'). + * This pattern is added as an nested exclude the scalac task. + */ + private List scalaExcludes; + + private AntScalaCompile antScalaCompile; + + private ScalaCompileOptions scalaCompileOptions = new ScalaCompileOptions(); + + public ScalaCompile(Project project, String name) { + super(project, name); + setActions(new ArrayList()); + doFirst(new TaskAction() { + public void execute(Task task) { + compile(task); + } + }); + } + + public AntScalaCompile getAntScalaCompile() { + if (antScalaCompile == null) { + antScalaCompile = new AntScalaCompile(getAnt()); + } + return antScalaCompile; + } + + public void setAntScalaCompile(AntScalaCompile antScalaCompile) { + this.antScalaCompile = antScalaCompile; + } + + public List getScalaSourceDirs() { + return (List) conv(scalaSourceDirs, "scalaSourceDirs"); + } + + public void setScalaSourceDirs(List scalaSourceDirs) { + this.scalaSourceDirs = scalaSourceDirs; + } + + public List getScalaIncludes() { + return scalaIncludes; + } + + public void setScalaIncludes(List scalaIncludes) { + this.scalaIncludes = scalaIncludes; + } + + public List getScalaExcludes() { + return scalaExcludes; + } + + public void setScalaExcludes(List scalaExcludes) { + this.scalaExcludes = scalaExcludes; + } + + public ScalaCompileOptions getScalaCompileOptions() { + return scalaCompileOptions; + } + + public void setScalaCompileOptions(ScalaCompileOptions scalaCompileOptions) { + this.scalaCompileOptions = scalaCompileOptions; + } + + @Override + protected void compile(Task task) { + + if (!GUtil.isTrue(getTargetCompatibility())) { + throw new InvalidUserDataException("The targetCompatibility must be set!"); + } + + List existingSourceDirs = existentDirsFilter.checkDestDirAndFindExistingDirsAndThrowStopActionIfNone( + getDestinationDir(), getScalaSourceDirs()); + + getAntScalaCompile().execute(existingSourceDirs, getScalaIncludes(), getScalaExcludes(), getDestinationDir(), + getClasspath(), getScalaCompileOptions()); + } + +} Index: src/samples/scalaproject/api/src/test/scala/org/gradle/sample/impl/PersonImplTest.scala =================================================================== --- src/samples/scalaproject/api/src/test/scala/org/gradle/sample/impl/PersonImplTest.scala Tue Nov 04 21:54:00 EST 2008 +++ src/samples/scalaproject/api/src/test/scala/org/gradle/sample/impl/PersonImplTest.scala Tue Nov 04 21:54:00 EST 2008 @@ -0,0 +1,14 @@ +package org.gradle.sample.impl + +import _root_.junit.framework.TestCase +import _root_.org.gradle.sample.api.Person + +class PersonImplTest extends TestCase { + + // FIXME: use a Scala test framework to run a test + def testCanCreatePersonImpl(): Unit = { + def person: Person = new PersonImpl(List("bob", "smith")) + person + } + +} Index: src/samples/scalaproject/api/src/main/scala/org/gradle/sample/api/Person.scala =================================================================== --- src/samples/scalaproject/api/src/main/scala/org/gradle/sample/api/Person.scala Tue Nov 04 18:50:02 EST 2008 +++ src/samples/scalaproject/api/src/main/scala/org/gradle/sample/api/Person.scala Tue Nov 04 18:50:02 EST 2008 @@ -0,0 +1,9 @@ +package org.gradle.sample.api + +/** + * Defines the interface for a person. + */ +abstract trait Person +{ + def names: List[String] +} Index: src/samples/scalaproject/api/src/main/scala/org/gradle/sample/impl/PersonImpl.scala =================================================================== --- src/samples/scalaproject/api/src/main/scala/org/gradle/sample/impl/PersonImpl.scala Tue Nov 04 18:51:00 EST 2008 +++ src/samples/scalaproject/api/src/main/scala/org/gradle/sample/impl/PersonImpl.scala Tue Nov 04 18:51:00 EST 2008 @@ -0,0 +1,11 @@ +package org.gradle.sample.impl + +import org.gradle.sample.api.Person + +/** + * Immutable implementation of { @link Person }. + */ +class PersonImpl(val names: List[String]) extends Person +{ + +} Index: src/main/groovy/org/gradle/api/plugins/scala/ScalaDoc.java =================================================================== --- src/main/groovy/org/gradle/api/plugins/scala/ScalaDoc.java Tue Nov 04 21:25:29 EST 2008 +++ src/main/groovy/org/gradle/api/plugins/scala/ScalaDoc.java Tue Nov 04 21:25:29 EST 2008 @@ -0,0 +1,144 @@ +package org.gradle.api.plugins.scala; + +import org.gradle.api.DependencyManager; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.TaskAction; +import org.gradle.api.internal.ConventionTask; +import org.gradle.api.tasks.util.ExistingDirsFilter; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Task to perform scala compilation. + */ +public class ScalaDoc extends ConventionTask { + + /** + * The directory to put the generated documentation. + */ + private File destinationDir; + + /** + * Directories containing input scala source files. + */ + private List scalaSourceDirs; + + /** + * Include pattern for which scala files should be compiled (e.g. '**F;org/gradle/package1/')). + */ + private List scalaIncludes; + + /** + * Exclude pattern for which scala files should be compiled (e.g. '**F;org/gradle/package2/A*.java'). + */ + private List scalaExcludes; + + private DependencyManager dependencyManager; + + private AntScalaDoc antScalaDoc; + + private ScalaDocOptions scalaDocOptions = new ScalaDocOptions(); + + private ExistingDirsFilter existentDirsFilter = new ExistingDirsFilter(); + + public ScalaDoc(Project project, String name) { + super(project, name); + setActions(new ArrayList()); + doFirst(new TaskAction() { + public void execute(Task task) { + generate(task); + } + }); + } + + public AntScalaDoc getAntScalaDoc() { + if (antScalaDoc == null) { + antScalaDoc = new AntScalaDoc(getAnt()); + } + return antScalaDoc; + } + + public void setAntScalaDoc(AntScalaDoc antScalaDoc) { + this.antScalaDoc = antScalaDoc; + } + + public File getDestinationDir() { + return (File) conv(destinationDir, "destinationDir"); + } + + public void setDestinationDir(File destinationDir) { + this.destinationDir = destinationDir; + } + + public List getScalaSourceDirs() { + return (List) conv(scalaSourceDirs, "scalaSourceDirs"); + } + + public void setScalaSourceDirs(List scalaSourceDirs) { + this.scalaSourceDirs = scalaSourceDirs; + } + + /** + *

Returns the classpath to use to locate classes referenced by the documented source.

+ * + * @return The classpath. + */ + public List getClasspath() { + return getDependencyManager().resolveTask(getName()); + } + + /** + *

Returns the {@link DependencyManager} which this task uses to resolve the classpath to use when generating the + * documentation.

+ * + * @return The dependency manager. + */ + public DependencyManager getDependencyManager() { + return (DependencyManager) conv(dependencyManager, "dependencyManager"); + } + + /** + *

Sets the {@link DependencyManager} which this task uses to resolve the classpath to use when generating the + * documentation.

+ */ + public void setDependencyManager(DependencyManager dependencyManager) { + this.dependencyManager = dependencyManager; + } + + public List getScalaIncludes() { + return (List) conv(scalaIncludes, "scalaIncludes"); + } + + public void setScalaIncludes(List scalaIncludes) { + this.scalaIncludes = scalaIncludes; + } + + public List getScalaExcludes() { + return (List) conv(scalaExcludes, "scalaExcludes"); + } + + public void setScalaExcludes(List scalaExcludes) { + this.scalaExcludes = scalaExcludes; + } + + public ScalaDocOptions getScalaDocOptions() { + return scalaDocOptions; + } + + public void setScalaDocOptions(ScalaDocOptions scalaDocOptions) { + this.scalaDocOptions = scalaDocOptions; + } + + protected void generate(Task task) { + + List existingSourceDirs = existentDirsFilter.checkDestDirAndFindExistingDirsAndThrowStopActionIfNone( + getDestinationDir(), getScalaSourceDirs()); + + getAntScalaDoc().execute(existingSourceDirs, getScalaIncludes(), getScalaExcludes(), getDestinationDir(), + getClasspath(), getScalaDocOptions()); + } + +} Index: src/main/groovy/org/gradle/api/plugins/scala/ScalaDocOptions.groovy =================================================================== --- src/main/groovy/org/gradle/api/plugins/scala/ScalaDocOptions.groovy Tue Nov 04 21:23:02 EST 2008 +++ src/main/groovy/org/gradle/api/plugins/scala/ScalaDocOptions.groovy Tue Nov 04 21:23:02 EST 2008 @@ -0,0 +1,77 @@ +package org.gradle.api.plugins.scala + +import org.gradle.api.tasks.compile.AbstractOptions + +public class ScalaDocOptions extends AbstractOptions { + + /** + * Generate deprecation information. + */ + boolean deprecation = true + + /** + * Generate unchecked information. + */ + boolean unchecked = true + + /** + * Text to appear in the window title. + */ + String windowTitle + + /** + * Html text to appear in the main frame title. + */ + String docTitle + + /** + * Html text to appear in the header for each page. + */ + String header + + /** + * Html text to appear in the footer for each page. + */ + String footer + + /** + * Html text to appear in the top text for each page. + */ + String top + + /** + * Html text to appear in the bottom text for each page. + */ + String bottom + + /** + * Style sheet to override default style. + */ + File styleSheet + + /** + * Additional parameters passed to the compiler. + * Each parameter must start with '-'. + */ + List additionalParameters + + + Map fieldName2AntMap() { + [ + additionalParameters: 'addParams' + ] + } + + Map fieldValue2AntMap() { + [ + deprecation: {toBooleanString(deprecation)}, + unchecked: {toBooleanString(unchecked)}, + additionalParameters: {additionalParameters.isEmpty() ? ' ' : additionalParameters.join(' ')}, + ] + } + + private String toBooleanString(value) { + return value ? 'on' : 'off' + } + +} Index: src/samples/scalaproject/api/build.gradle =================================================================== --- src/samples/scalaproject/api/build.gradle Tue Nov 04 21:50:37 EST 2008 +++ src/samples/scalaproject/api/build.gradle Tue Nov 04 21:50:37 EST 2008 @@ -0,0 +1,14 @@ +usePlugin('scala') + +targetCompatibility = 1.5 + +dependencies { + addMavenStyleRepo('scala-releases', 'http://scala-tools.org/repo-releases/') + + // Libraries needed to run the scala tools + scalaTools 'org.scala-lang:scala-compiler:2.7.1' + scalaTools 'org.scala-lang:scala-library:2.7.1' + + compile 'org.scala-lang:scala-library:2.7.1' + testCompile ":junit:4.4" +} Index: src/main/groovy/org/gradle/api/plugins/scala/ScalaPlugin.java =================================================================== --- src/main/groovy/org/gradle/api/plugins/scala/ScalaPlugin.java Tue Nov 04 21:33:24 EST 2008 +++ src/main/groovy/org/gradle/api/plugins/scala/ScalaPlugin.java Tue Nov 04 21:33:24 EST 2008 @@ -0,0 +1,110 @@ +package org.gradle.api.plugins.scala; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.internal.project.PluginRegistry; +import org.gradle.api.plugins.Convention; +import org.gradle.api.plugins.DefaultConventionsToPropertiesMapping; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.tasks.ConventionValue; +import org.gradle.api.tasks.compile.Compile; +import org.gradle.api.tasks.testing.ForkMode; +import org.gradle.api.tasks.testing.Test; +import org.gradle.util.GUtil; + +import java.util.Arrays; +import java.util.Map; + +public class ScalaPlugin extends JavaPlugin { + // public configurations + public static final String SCALA_TOOLS = "scalaTools"; + + // tasks + private static final String SCALA_DOC_TASK = "scalaDoc"; + private static final String SCALA_DEFINE_TASK = "defineScalaAnt"; + + @Override + public void apply(Project project, PluginRegistry pluginRegistry, Map customValues) { + pluginRegistry.apply(JavaPlugin.class, project, pluginRegistry, customValues); + ScalaPluginConvention scalaPluginConvention = new ScalaPluginConvention(project, customValues); + project.getConvention().getPlugins().put("scala", scalaPluginConvention); + + configureDefine(project); + configureCompile(project); + configureTestCompile(project); + + ((Test) project.task(TEST)).getOptions().getForkOptions().setForkMode(ForkMode.ONCE); + + configureScaladoc(project); + + project.getDependencies().addConfiguration(SCALA_TOOLS).setVisible(false).setTransitive(false); + project.getDependencies().linkConfWithTask(SCALA_TOOLS, SCALA_DEFINE_TASK); + project.getDependencies().linkConfWithTask(COMPILE, SCALA_DOC_TASK); + } + + private void configureDefine(Project project) { + ScalaDefine defineTask = (ScalaDefine) project.createTask( + GUtil.map("type", ScalaDefine.class, "dependsOn", RESOURCES, "overwrite", true), SCALA_DEFINE_TASK); + defineTask.conventionMapping(GUtil.map( + "dependencyManager", new ConventionValue() { + public Object getValue(Convention convention, Task task) { + return task.getProject().getDependencies(); + } + } + )); + } + + private void configureScaladoc(Project project) { + ScalaDoc docTask = (ScalaDoc) project.createTask( + GUtil.map("type", ScalaDoc.class, "dependsOn", SCALA_DEFINE_TASK), SCALA_DOC_TASK); + docTask.conventionMapping(GUtil.map( + "dependencyManager", new ConventionValue() { + public Object getValue(Convention convention, Task task) { + return task.getProject().getDependencies(); + } + }, + "destinationDir", new ConventionValue() { + public Object getValue(Convention convention, Task task) { + return scala(convention).getScalaDocDir(); + } + }, + "scalaSourceDirs", new ConventionValue() { + public Object getValue(Convention convention, Task task) { + return scala(convention).getScalaSrcDirs(); + } + } + )); + } + + private void configureCompile(Project project) { + ScalaCompile compileTask = (ScalaCompile) project.createTask( + GUtil.map("type", ScalaCompile.class, "dependsOn", Arrays.asList(SCALA_DEFINE_TASK, RESOURCES), "overwrite", true), COMPILE); + configureCompile(compileTask, DefaultConventionsToPropertiesMapping.COMPILE); + compileTask.conventionMapping(GUtil.map( + "scalaSourceDirs", new ConventionValue() { + public Object getValue(Convention convention, Task task) { + return scala(convention).getScalaSrcDirs(); + } + } + )); + } + + private void configureTestCompile(Project project) { + ScalaCompile testCompileTask = (ScalaCompile) project.createTask( + GUtil.map("type", ScalaCompile.class, "dependsOn", Arrays.asList(SCALA_DEFINE_TASK, TEST_RESOURCES), "overwrite", true), TEST_COMPILE); + configureTestCompile(testCompileTask, (Compile) project.task(COMPILE), + DefaultConventionsToPropertiesMapping.TEST_COMPILE); + testCompileTask.conventionMapping(GUtil.map( + "scalaSourceDirs", new ConventionValue() { + public Object getValue(Convention convention, Task task) { + return scala(convention).getScalaTestSrcDirs(); + } + } + )); + } + + private ScalaPluginConvention scala(Convention convention) { + return (ScalaPluginConvention) convention.getPlugins().get("scala"); + } + +}