aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDierk König <dierk.koenig@canoo.com>2015-11-21 10:09:31 +0100
committerDierk König <dierk.koenig@canoo.com>2015-11-21 10:09:31 +0100
commitf0807811f48c50b6a5fe7816ef48c148be9f9903 (patch)
treec61df925b637d26c95086510ee471ac861a36731
parentfa6dce676590c83bc84d130e1241cf585f88a469 (diff)
parent73dd702743a5b4d8816e495e55c19f391669fc25 (diff)
downloadfrege-gradle-plugin-f0807811f48c50b6a5fe7816ef48c148be9f9903.tar.gz
frege-gradle-plugin-f0807811f48c50b6a5fe7816ef48c148be9f9903.tar.bz2
frege-gradle-plugin-f0807811f48c50b6a5fe7816ef48c148be9f9903.zip
Merge pull request #28 from breskeby/base-plugin
Base plugin
-rw-r--r--src/integTest/groovy/frege/plugin/FregePluginIntegTest.groovy49
-rw-r--r--src/main/groovy/frege/gradle/CompileTask.groovy273
-rw-r--r--src/main/groovy/frege/gradle/DefaultFregeSourceSet.java33
-rw-r--r--src/main/groovy/frege/gradle/FregePlugin.groovy46
-rw-r--r--src/main/groovy/frege/gradle/FregeSourceSet.java7
-rw-r--r--src/main/groovy/frege/gradle/plugins/FregeBasePlugin.java87
-rw-r--r--src/main/groovy/frege/gradle/plugins/FregeJarFile.java34
-rw-r--r--src/main/groovy/frege/gradle/plugins/FregePlugin.groovy34
-rw-r--r--src/main/groovy/frege/gradle/plugins/FregePluginExtension.groovy (renamed from src/main/groovy/frege/gradle/FregePluginExtension.groovy)2
-rw-r--r--src/main/groovy/frege/gradle/plugins/FregeRuntime.java63
-rw-r--r--src/main/groovy/frege/gradle/tasks/FregeCompile.groovy198
-rw-r--r--src/main/groovy/frege/gradle/tasks/FregeDoc.groovy (renamed from src/main/groovy/frege/gradle/DocTask.groovy)4
-rw-r--r--src/main/groovy/frege/gradle/tasks/FregeNativeGen.groovy (renamed from src/main/groovy/frege/gradle/NativeGenTask.groovy)4
-rw-r--r--src/main/groovy/frege/gradle/tasks/FregeQuickCheck.groovy (renamed from src/main/groovy/frege/gradle/QuickCheckTask.groovy)8
-rw-r--r--src/main/groovy/frege/gradle/tasks/FregeRepl.groovy (renamed from src/main/groovy/frege/gradle/ReplTask.groovy)4
-rw-r--r--src/main/resources/META-INF/gradle-plugins/org.frege-lang.base.properties1
-rw-r--r--src/main/resources/META-INF/gradle-plugins/org.frege-lang.properties2
-rw-r--r--src/test/groovy/frege/gradle/FregeBasePluginTest.groovy31
-rw-r--r--src/test/groovy/frege/gradle/FregePluginTest.groovy32
19 files changed, 570 insertions, 342 deletions
diff --git a/src/integTest/groovy/frege/plugin/FregePluginIntegTest.groovy b/src/integTest/groovy/frege/plugin/FregePluginIntegTest.groovy
index 5c985e8..b6936a8 100644
--- a/src/integTest/groovy/frege/plugin/FregePluginIntegTest.groovy
+++ b/src/integTest/groovy/frege/plugin/FregePluginIntegTest.groovy
@@ -1,14 +1,15 @@
package frege.plugin
-
import org.gradle.testkit.runner.GradleRunner
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import spock.lang.Specification
+import spock.lang.Unroll
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class FregePluginIntegTest extends Specification {
+ public static final String DEFAULT_FREGE_VERSION = "3.23.370-g898bc8c"
@Rule
final TemporaryFolder testProjectDir = new TemporaryFolder()
File buildFile
@@ -18,6 +19,15 @@ class FregePluginIntegTest extends Specification {
def setup() {
buildFile = testProjectDir.newFile('build.gradle')
+ buildFile << """
+ plugins {
+ id 'org.frege-lang'
+ }
+
+ repositories {
+ jcenter()
+ }
+ """
def pluginClasspathResource = getClass().classLoader.findResource("plugin-classpath.txt")
if (pluginClasspathResource == null) {
// try again via file reference
@@ -29,26 +39,39 @@ class FregePluginIntegTest extends Specification {
pluginClasspath = pluginClasspathResource.readLines().collect { new File(it) }
}
- def "can compile frege production code"() {
+ def "can handle non existing source directories"() {
given:
buildFile << """
- plugins {
- id 'org.frege-lang'
+ dependencies {
+ compile "org.frege-lang:frege:$DEFAULT_FREGE_VERSION"
}
+ """
- repositories {
- jcenter()
- }
+ when:
+ def result = GradleRunner.create()
+ .withProjectDir(testProjectDir.root)
+ .withArguments('classes')
+ .withPluginClasspath(pluginClasspath)
+ .build()
+ then:
+ result.task(":compileFrege") != null
+ }
+ @Unroll
+ def "can compile and run frege code (gradle: #gradleVersion, frege: #fregeVersion)"() {
+ given:
+ buildFile << """
dependencies {
- compile "org.frege-lang:frege:3.22.367-g2737683"
+ compile "org.frege-lang:frege:$fregeVersion"
}
task sayHello(type: JavaExec){
+ doFirst {
+ println classpath.files
+ }
classpath = sourceSets.main.runtimeClasspath
main = 'HelloFrege'
}
-
"""
testProjectDir.newFolder("src", "main", "frege")
@@ -65,6 +88,7 @@ main _ = do
when:
def result = GradleRunner.create()
+ .withGradleVersion(gradleVersion)
.withProjectDir(testProjectDir.root)
.withArguments('sayHello')
.withPluginClasspath(pluginClasspath)
@@ -73,5 +97,12 @@ main _ = do
then:
result.output.contains("Hello Frege!")
result.task(":sayHello").outcome == SUCCESS
+
+ where:
+ fregeVersion | gradleVersion
+ DEFAULT_FREGE_VERSION | "2.9"
+ DEFAULT_FREGE_VERSION | "2.8"
+ "3.22.367-g2737683" | "2.9"
+ "3.22.367-g2737683" | "2.8"
}
} \ No newline at end of file
diff --git a/src/main/groovy/frege/gradle/CompileTask.groovy b/src/main/groovy/frege/gradle/CompileTask.groovy
deleted file mode 100644
index 07850a5..0000000
--- a/src/main/groovy/frege/gradle/CompileTask.groovy
+++ /dev/null
@@ -1,273 +0,0 @@
-package frege.gradle
-
-import frege.compiler.Main
-import frege.prelude.PreludeBase
-import frege.runtime.Lambda
-import groovy.transform.TypeChecked
-import groovy.transform.TypeCheckingMode
-import org.gradle.api.DefaultTask
-import org.gradle.api.Project
-import org.gradle.api.artifacts.Configuration
-import org.gradle.api.file.FileCollection
-import org.gradle.api.tasks.*
-import org.gradle.process.internal.DefaultJavaExecAction
-import org.gradle.process.internal.JavaExecAction
-import org.gradle.api.internal.file.FileResolver
-
-@TypeChecked
-class CompileTask extends DefaultTask {
-
- // see help at https://github.com/Frege/frege/wiki/Compiler-Manpage
-
- static String DEFAULT_CLASSES_SUBDIR = "classes/main" // TODO: should this come from a convention?
- static String DEFAULT_SRC_DIR = "src/main/frege" // TODO: should this come from a source set?
-
- static String DEFAULT_TEST_CLASSES_DIR = "classes/test"
- static String DEFAULT_TEST_SRC_DIR = "src/test/frege"
-
- static Boolean USE_EXTERNAl = true
-
- @Optional @Input
- boolean enabled = true
-
- @Optional @Input
- Boolean help = false
-
- @Optional @Input
- String stackSize = "4m"
-
- @Optional @Input
- boolean hints = false
-
- @Optional @Input
- boolean optimize = false
-
- @Optional @Input
- boolean verbose = false
-
- @Optional @Input
- boolean inline = true
-
- @Optional @Input
- boolean make = true
-
- @Optional @Input
- boolean compileGeneratedJava = true
-
- @Optional @Input
- String target = ""
-
- @Optional @Input
- boolean comments = false
-
- @Optional @Input
- boolean suppressWarnings = false
-
- @Optional @Input
- String explain = ""
-
- @Optional @Input
- boolean skipCompile = false
-
- @Optional @Input
- String extraArgs = ""
-
- @Optional @Input
- String allArgs = "" // this is an option to overrule all other settings
-
- @Optional @Input
- String module = ""
-
- @Optional @Input
- List<File> fregePaths = []
-
- @Optional @Input
- List<File> sourcePaths = [deduceSourceDir(project)]
-
- @Optional @OutputDirectory
- File outputDir = deduceClassesDir(project)
-
- @Optional @Input
- String mainClass = "frege.compiler.Main"
-
- @Optional @Input
- List<String> allJvmArgs = []
-
- @Optional @Input
- String encoding = ""
-
- @Optional @Input
- String prefix = ""
-
- // TODO: Missing presentation of types (ascii, symbols, latin, greek, faktur)
-
- static File deduceSourceDir(File projectDir, String subdir) {
- new File(projectDir, subdir)
- }
-
- static File deduceSourceDir(Project project) {
- deduceSourceDir(project.projectDir, DEFAULT_SRC_DIR)
- }
-
- static File deduceClassesDir(File projectDir, String subdir) {
- new File(projectDir, subdir)
- }
-
- static File deduceClassesDir(Project project) {
- deduceClassesDir(project.buildDir, DEFAULT_CLASSES_SUBDIR)
- }
-
- static File deduceTestClassesDir(Project project) {
- deduceClassesDir(project.buildDir, DEFAULT_TEST_CLASSES_DIR)
- }
-
- static File deduceTestSourceDir(Project project) {
- deduceSourceDir(project.projectDir, DEFAULT_TEST_SRC_DIR)
- }
-
- @TaskAction
- void executeCompile() {
-
- if (!enabled) {
- logger.info("Frege compiler disabled.")
- return;
- }
-
- if (!outputDir.exists() ) {
- logger.info "Creating output directory '${outputDir.absolutePath}'."
- outputDir.mkdirs()
- }
- // access extension configuration values as ${project.frege.key1}
-
- FileResolver fileResolver = getServices().get(FileResolver.class)
- JavaExecAction action = new DefaultJavaExecAction(fileResolver)
- action.setMain(mainClass)
-
- logConfigurationInfo()
-
- action.setClasspath(actionClasspath(project))
-
- def args = []
- if (help) {
- args << "-help"
- } else {
- def jvmArgs = allJvmArgs
- if (jvmArgs.isEmpty()) {
- jvmArgs << "-Xss$stackSize".toString()
- }
- action.setJvmArgs(jvmArgs)
- args = allArgs ? allArgs.split().toList() : assembleArguments()
- }
-
- logger.info("Calling Frege compiler with args: '$args'")
- action.args(args)
-
- if (USE_EXTERNAl) {
- action.execute()
- } else {
- compile(args as String[])
- }
- }
-
- void logConfigurationInfo() {
- def path = project.files(compileConfig()).getAsPath()
- logger.info("Compile configuation as path: $path")
-
- }
-
- FileCollection actionClasspath(Project p) {
- p.files(compileConfig()) + p.files(deduceClassesDir(p))
- }
-
- // TODO: This should be removed or integrated so an external Java process does not need to be started.
- // The Java generated uses System.exit() which does not work well with Gradle
- // This was taken from the frege fork /compiler1/build/classes/main/afrege/compiler/Main.java:main()
- void compile(String[] paramArrayOfString) {
- long l1 = System.nanoTime();
- Integer localInteger = frege.runtime.Runtime.runMain(
- PreludeBase.TST.performUnsafe(
- (Lambda)Main.IJ._mainƒd0fa0028.inst.apply(PreludeBase._toList(paramArrayOfString)).forced()
- )
- );
- long l2 = System.nanoTime();
- ((PrintWriter)frege.runtime.Runtime.stderr.get()).println("runtime " + (l2 - l1 + 500000L) / 1000000L / 1000.0D + " wallclock seconds.");
- if (localInteger != null) {
-// System.exit(localInteger.intValue());
- }
- }
-
- List<File> totalFregeClasspath(List<File> fp) {
- def result = []
- result.addAll(project.files(compileConfig()).getFiles().toList())
- result.addAll(fp)
- result
- }
-
- @TypeChecked(TypeCheckingMode.SKIP)
- Configuration compileConfig() {
- project.configurations.compile
- }
-
- protected List<String> assembleArguments() {
- List args = []
- if (hints)
- args << "-hints"
- if (optimize) {
- args << "-O"
- args << "-inline"
- }
- if (inline & !optimize)
- args << "-inline"
- if (make)
- args << "-make"
- if (!compileGeneratedJava) args << "-j"
- if (target != "") {
- args << "-target"
- args << target
- }
- if (comments) args << "-comments"
- if (suppressWarnings) args << "-nowarn"
- if (explain != "") {
- args << "-explain"
- args << explain
- }
- if (verbose)
- args << "-v"
- if (skipCompile)
- args << "-j"
-
- def fp = USE_EXTERNAl ? fregePaths : totalFregeClasspath(fregePaths)
- if (!fp.isEmpty()) {
- args << "-fp"
- args << fp.collect{f -> f.absolutePath}.join(File.pathSeparator)
- }
-
- if (sourcePaths != null && !sourcePaths.isEmpty()) {
- args << "-sp"
- args << sourcePaths.collect{d -> d.absolutePath}.join(File.pathSeparator)
- }
-
- if (encoding != "") {
- args << "-enc"
- args << encoding
- }
-
- if (prefix != "") {
- args << "-prefix"
- args << prefix
- }
-
- args << "-d"
- args << outputDir
-
- if (!module.isEmpty()) {
- logger.info "compiling module '$module'"
- args << module
- } else {
- args = (args + extraArgs.split().toList()).toList()
- }
-
- args
- }
-
-}
diff --git a/src/main/groovy/frege/gradle/DefaultFregeSourceSet.java b/src/main/groovy/frege/gradle/DefaultFregeSourceSet.java
new file mode 100644
index 0000000..3a9bcfc
--- /dev/null
+++ b/src/main/groovy/frege/gradle/DefaultFregeSourceSet.java
@@ -0,0 +1,33 @@
+package frege.gradle;
+
+import groovy.lang.Closure;
+import org.gradle.api.file.SourceDirectorySet;
+import org.gradle.api.internal.file.DefaultSourceDirectorySet;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.util.ConfigureUtil;
+
+public class DefaultFregeSourceSet implements FregeSourceSet {
+ private final SourceDirectorySet frege;
+ private final SourceDirectorySet allFrege;
+
+ public DefaultFregeSourceSet(String displayName, FileResolver fileResolver) {
+ this.frege = new DefaultSourceDirectorySet(String.format("%s Frege source", new Object[]{displayName}), fileResolver);
+ this.frege.getFilter().include(new String[]{"**/*.fr"});
+ this.allFrege = new DefaultSourceDirectorySet(String.format("%s Frege source", new Object[]{displayName}), fileResolver);
+ this.allFrege.source(this.frege);
+ this.allFrege.getFilter().include(new String[]{"**/*.fr"});
+ }
+
+ public SourceDirectorySet getFrege() {
+ return this.frege;
+ }
+
+ public FregeSourceSet frege(Closure configureClosure) {
+ ConfigureUtil.configure(configureClosure, this.getFrege());
+ return this;
+ }
+
+ public SourceDirectorySet getAllFrege() {
+ return this.allFrege;
+ }
+}
diff --git a/src/main/groovy/frege/gradle/FregePlugin.groovy b/src/main/groovy/frege/gradle/FregePlugin.groovy
deleted file mode 100644
index 29be393..0000000
--- a/src/main/groovy/frege/gradle/FregePlugin.groovy
+++ /dev/null
@@ -1,46 +0,0 @@
-package frege.gradle
-
-import groovy.transform.TypeChecked
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import fj.data.Option
-import org.gradle.api.plugins.JavaPlugin
-
-//@TypeChecked
-class FregePlugin implements Plugin<Project> {
-
- void apply(Project project) {
- // Workaround to build proper jars on Windows, see https://github.com/Frege/frege-gradle-plugin/issues/9
- System.setProperty("file.encoding", "UTF-8")
-
- project.plugins.apply(JavaPlugin)
- def e = (FregePluginExtension) project.extensions.create("frege", FregePluginExtension)
-
- project.task('compileFrege', type: CompileTask, group: 'Build', dependsOn: "compileJava") {
- module = CompileTask.deduceSourceDir(project).absolutePath
- }
- project.tasks.classes.dependsOn("compileFrege")
-
- project.task('compileTestFrege', type: CompileTask, group: 'Build', dependsOn: "compileTestJava") {
- module = CompileTask.deduceTestSourceDir(project).absolutePath
- outputDir = CompileTask.deduceTestClassesDir(project)
- fregePaths = Option.fromNull(CompileTask.deduceClassesDir(project))
- .map{d -> [d]}.orSome([])
- }
- project.tasks.testClasses.dependsOn("compileTestFrege")
-
- def replTask = project.task('fregeRepl', type: ReplTask, group: 'Tools', dependsOn: 'compileFrege')
- replTask.outputs.upToDateWhen { false } // always run, regardless of up to date checks
-
- def checkTask = project.task('fregeQuickCheck', type: QuickCheckTask, group: 'Verification', dependsOn: 'testClasses')
- checkTask.outputs.upToDateWhen { false } // always run, regardless of up to date checks
-
- project.tasks.test.dependsOn("fregeQuickCheck")
-
- project.task('fregeDoc', type: DocTask, group: 'Documentation', dependsOn: 'compileFrege')
-
- project.task('fregeNativeGen', type: NativeGenTask, group: 'Tools')
-
- }
-
-}
diff --git a/src/main/groovy/frege/gradle/FregeSourceSet.java b/src/main/groovy/frege/gradle/FregeSourceSet.java
new file mode 100644
index 0000000..8706ee2
--- /dev/null
+++ b/src/main/groovy/frege/gradle/FregeSourceSet.java
@@ -0,0 +1,7 @@
+package frege.gradle;
+
+/**
+ * Created by Rene on 20/11/15.
+ */
+public interface FregeSourceSet {
+}
diff --git a/src/main/groovy/frege/gradle/plugins/FregeBasePlugin.java b/src/main/groovy/frege/gradle/plugins/FregeBasePlugin.java
new file mode 100644
index 0000000..8bf5399
--- /dev/null
+++ b/src/main/groovy/frege/gradle/plugins/FregeBasePlugin.java
@@ -0,0 +1,87 @@
+package frege.gradle.plugins;
+
+import frege.gradle.DefaultFregeSourceSet;
+import frege.gradle.tasks.FregeCompile;
+import org.gradle.api.Action;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.file.FileTreeElement;
+import org.gradle.api.internal.file.FileResolver;
+import org.gradle.api.internal.plugins.DslObject;
+import org.gradle.api.internal.tasks.DefaultSourceSet;
+import org.gradle.api.plugins.JavaBasePlugin;
+import org.gradle.api.plugins.JavaPluginConvention;
+import org.gradle.api.specs.Spec;
+import org.gradle.api.tasks.SourceSet;
+
+import javax.inject.Inject;
+import java.util.concurrent.Callable;
+
+public class FregeBasePlugin implements Plugin<Project> {
+ private FileResolver fileResolver;
+
+ private static String EXTENSION_NAME = "frege";
+ private FregePluginExtension fregePluginExtension;
+ private Project project;
+
+ @Inject
+ public FregeBasePlugin(FileResolver fileResolver) {
+ this.fileResolver = fileResolver;
+ }
+
+ @Override
+ public void apply(Project project) {
+ // Workaround to build proper jars on Windows, see https://github.com/Frege/frege-gradle-plugin/issues/9
+ this.project = project;
+ System.setProperty("file.encoding", "UTF-8");
+ project.getPluginManager().apply(JavaBasePlugin.class);
+ fregePluginExtension = project.getExtensions().create(EXTENSION_NAME, FregePluginExtension.class);
+ JavaBasePlugin javaBasePlugin = project.getPlugins().getPlugin(JavaBasePlugin.class);
+
+ configureCompileDefaults(new FregeRuntime(project));
+ configureSourceSetDefaults(javaBasePlugin);
+ }
+
+
+ private void configureSourceSetDefaults(final JavaBasePlugin javaBasePlugin) {
+ project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().all(new Action<SourceSet>() {
+ public void execute(SourceSet sourceSet) {
+ final DefaultFregeSourceSet fregeSourceSet = new DefaultFregeSourceSet(((DefaultSourceSet) sourceSet).getDisplayName(), fileResolver);
+ new DslObject(sourceSet).getConvention().getPlugins().put("frege", fregeSourceSet);
+
+ final String defaultSourcePath = String.format("src/%s/frege", sourceSet.getName());
+ fregeSourceSet.getFrege().srcDir(defaultSourcePath);
+ sourceSet.getResources().getFilter().exclude(new Spec<FileTreeElement>() {
+ public boolean isSatisfiedBy(FileTreeElement element) {
+ return fregeSourceSet.getFrege().contains(element.getFile());
+ }
+ });
+ sourceSet.getAllJava().source(fregeSourceSet.getFrege());
+ sourceSet.getAllSource().source(fregeSourceSet.getFrege());
+
+ String compileTaskName = sourceSet.getCompileTaskName("frege");
+ FregeCompile compile = project.getTasks().create(compileTaskName, FregeCompile.class);
+ compile.setModule(project.file(defaultSourcePath).getAbsolutePath());
+ javaBasePlugin.configureForSourceSet(sourceSet, compile);
+ compile.dependsOn(sourceSet.getCompileJavaTaskName());
+ compile.setDescription(String.format("Compiles the %s Frege source.", sourceSet.getName()));
+ compile.setSource(fregeSourceSet.getFrege());
+ project.getTasks().getByName(sourceSet.getClassesTaskName()).dependsOn(compileTaskName);
+ }
+ });
+ }
+
+ private void configureCompileDefaults(final FregeRuntime fregeRuntime) {
+ this.project.getTasks().withType(FregeCompile.class, new Action<FregeCompile>() {
+ public void execute(final FregeCompile compile) {
+ compile.getConventionMapping().map("fregeClasspath", new Callable() {
+ public Object call() throws Exception {
+ return fregeRuntime.inferFregeClasspath(compile.getClasspath());
+ }
+
+ });
+ }
+ });
+ }
+
+}
diff --git a/src/main/groovy/frege/gradle/plugins/FregeJarFile.java b/src/main/groovy/frege/gradle/plugins/FregeJarFile.java
new file mode 100644
index 0000000..eaf7d8f
--- /dev/null
+++ b/src/main/groovy/frege/gradle/plugins/FregeJarFile.java
@@ -0,0 +1,34 @@
+package frege.gradle.plugins;
+
+import org.gradle.util.VersionNumber;
+
+import java.io.File;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class FregeJarFile {
+ private static final Pattern FILE_NAME_PATTERN = Pattern.compile("(frege(?:-all)?)-(\\d.*?)(-indy)?.jar");
+ private final File file;
+ private final Matcher matcher;
+ private String version;
+
+ private FregeJarFile(File file, Matcher matcher) {
+ this.file = file;
+ this.matcher = matcher;
+ }
+
+
+ public static FregeJarFile parse(File file) {
+ Matcher matcher = FILE_NAME_PATTERN.matcher(file.getName());
+ return matcher.matches() ? new FregeJarFile(file, matcher) : null;
+ }
+
+ public String getDependencyNotation() {
+ return "org.frege-lang:frege:" + getVersion();
+
+ }
+
+ public VersionNumber getVersion() {
+ return VersionNumber.parse(matcher.group(2));
+ }
+}
diff --git a/src/main/groovy/frege/gradle/plugins/FregePlugin.groovy b/src/main/groovy/frege/gradle/plugins/FregePlugin.groovy
new file mode 100644
index 0000000..af05228
--- /dev/null
+++ b/src/main/groovy/frege/gradle/plugins/FregePlugin.groovy
@@ -0,0 +1,34 @@
+package frege.gradle.plugins
+
+import frege.gradle.tasks.FregeDoc
+import frege.gradle.tasks.FregeNativeGen
+import frege.gradle.tasks.FregeQuickCheck
+import frege.gradle.tasks.FregeRepl
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+class FregePlugin implements Plugin<Project> {
+
+ Project project
+
+ void apply(Project project) {
+ this.project = project
+
+ project.plugins.apply(FregeBasePlugin)
+ project.plugins.apply("java")
+
+ def replTask = project.task('fregeRepl', type: FregeRepl, group: 'Tools', dependsOn: 'compileFrege')
+ replTask.outputs.upToDateWhen { false } // always run, regardless of up to date checks
+
+ def checkTask = project.task('fregeQuickCheck', type: FregeQuickCheck, group: 'Verification', dependsOn: 'testClasses')
+ checkTask.outputs.upToDateWhen { false } // always run, regardless of up to date checks
+
+ project.tasks.test.dependsOn("fregeQuickCheck")
+
+ project.task('fregeDoc', type: FregeDoc, group: 'Documentation', dependsOn: 'compileFrege')
+
+ project.task('fregeNativeGen', type: FregeNativeGen, group: 'Tools')
+
+ }
+
+}
diff --git a/src/main/groovy/frege/gradle/FregePluginExtension.groovy b/src/main/groovy/frege/gradle/plugins/FregePluginExtension.groovy
index dbf0d2a..ae180ec 100644
--- a/src/main/groovy/frege/gradle/FregePluginExtension.groovy
+++ b/src/main/groovy/frege/gradle/plugins/FregePluginExtension.groovy
@@ -1,4 +1,4 @@
-package frege.gradle
+package frege.gradle.plugins
/**
* Created by mperry on 6/02/2015.
diff --git a/src/main/groovy/frege/gradle/plugins/FregeRuntime.java b/src/main/groovy/frege/gradle/plugins/FregeRuntime.java
new file mode 100644
index 0000000..4265d0b
--- /dev/null
+++ b/src/main/groovy/frege/gradle/plugins/FregeRuntime.java
@@ -0,0 +1,63 @@
+package frege.gradle.plugins;
+
+import com.google.common.collect.Lists;
+import org.gradle.api.Buildable;
+import org.gradle.api.GradleException;
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.internal.file.collections.LazilyInitializedFileCollection;
+import org.gradle.api.internal.tasks.TaskDependencyResolveContext;
+
+import java.io.File;
+import java.util.List;
+
+public class FregeRuntime {
+
+ private final Project project;
+
+ public FregeRuntime(Project project) {
+ this.project = project;
+ }
+
+
+ public FileCollection inferFregeClasspath(final Iterable<File> classpath) {
+ return new LazilyInitializedFileCollection() {
+ public String getDisplayName() {
+ return "Frege runtime classpath";
+ }
+
+ public FileCollection createDelegate() {
+ final FregeJarFile fregeJar = FregeRuntime.this.findFregeJarFile(classpath);
+ if (fregeJar == null) {
+ throw new GradleException(String.format("Cannot infer Frege class path because no Frege Jar was found on class path: %s", classpath));
+ }
+ String notation = fregeJar.getDependencyNotation();
+ List<Dependency> dependencies = Lists.newArrayList();
+ dependencies.add(project.getDependencies().create(notation));
+ return project.getConfigurations().detachedConfiguration(dependencies.toArray(new Dependency[dependencies.size()]));
+ }
+
+ public void visitDependencies(TaskDependencyResolveContext context) {
+ if (classpath instanceof Buildable) {
+ context.add(classpath);
+ }
+ }
+
+ };
+ }
+
+ private FregeJarFile findFregeJarFile(Iterable<File> classpath) {
+ if (classpath == null) {
+ return null;
+ }
+ for (File file : classpath) {
+ FregeJarFile fregeJar = FregeJarFile.parse(file);
+ if (fregeJar != null) {
+ return fregeJar;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/groovy/frege/gradle/tasks/FregeCompile.groovy b/src/main/groovy/frege/gradle/tasks/FregeCompile.groovy
new file mode 100644
index 0000000..13b617c
--- /dev/null
+++ b/src/main/groovy/frege/gradle/tasks/FregeCompile.groovy
@@ -0,0 +1,198 @@
+package frege.gradle.tasks
+import groovy.transform.TypeChecked
+import groovy.transform.TypeCheckingMode
+import org.gradle.api.Action
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Optional
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.compile.AbstractCompile
+import org.gradle.process.JavaExecSpec
+
+@TypeChecked
+class FregeCompile extends AbstractCompile {
+
+ FileCollection fregeClasspath
+ FileCollection classpath
+
+ @Input
+ String stackSize = "4m"
+
+ @Optional
+ @Input
+ boolean hints = false
+
+ @Optional
+ @Input
+ boolean optimize = false
+
+ @Optional
+ @Input
+ boolean verbose = false
+
+ @Optional
+ @Input
+ boolean inline = true
+
+ @Optional
+ @Input
+ boolean make = true
+
+ @Optional
+ @Input
+ boolean compileGeneratedJava = true
+
+ @Optional
+ @Input
+ String target = ""
+
+ @Optional
+ @Input
+ boolean comments = false
+
+ @Optional
+ @Input
+ boolean suppressWarnings = false
+
+ @Optional
+ @Input
+ String explain = ""
+
+ @Optional
+ @Input
+ String extraArgs = ""
+
+ @Optional
+ @Input
+ String allArgs = "" // this is an option to overrule all other settings
+
+ @Optional
+ @Input
+ String module = ""
+
+ @Optional
+ @Input
+ List<File> fregePaths = []
+
+ @Input
+ String mainClass = "frege.compiler.Main"
+
+ @Optional
+ @Input
+ List<String> allJvmArgs = []
+
+ @Optional
+ @Input
+ String encoding = ""
+
+ @Optional
+ @Input
+ String prefix = ""
+
+ List<File> sourcePaths = []
+
+ @Override
+ @TaskAction
+ protected void compile() {
+ logConfigurationInfo()
+
+ def jvmArgs = allJvmArgs
+ if (jvmArgs.isEmpty()) {
+ jvmArgs << "-Xss$stackSize".toString()
+ }
+ def compilerArgs = allArgs ? allArgs.split().toList() : assembleArguments()
+
+ logger.info("Calling Frege compiler with compilerArgs: '$compilerArgs'")
+
+ //TODO integrate with gradle compiler daemon infrastructure and skip internal execution
+ project.javaexec(new Action<JavaExecSpec>() {
+ @Override
+ void execute(JavaExecSpec javaExecSpec) {
+ javaExecSpec.args = compilerArgs
+ javaExecSpec.classpath = FregeCompile.this.classpath + FregeCompile.this.fregeClasspath
+ javaExecSpec.main = mainClass
+ }
+ });
+ }
+
+ public FregeCompile source(Object... sources) {
+ super.source(sources);
+ // track directory roots
+ for (Object source : sources) {
+ sourcePaths.add(project.file(source))
+ }
+ return this;
+ }
+
+ void logConfigurationInfo() {
+ def path = project.files(compileConfig()).getAsPath()
+ logger.info("Compile configuation as path: $path")
+ }
+
+ @TypeChecked(TypeCheckingMode.SKIP)
+ Configuration compileConfig() {
+ project.configurations.compile
+ }
+
+ protected List<String> assembleArguments() {
+ List args = []
+ if (hints)
+ args << "-hints"
+ if (optimize) {
+ args << "-O"
+ args << "-inline"
+ }
+ if (inline & !optimize)
+ args << "-inline"
+ if (make)
+ args << "-make"
+ if (!compileGeneratedJava) args << "-j"
+ if (target != "") {
+ args << "-target"
+ args << target
+ }
+ if (comments) args << "-comments"
+ if (suppressWarnings) args << "-nowarn"
+ if (explain != "") {
+ args << "-explain"
+ args << explain
+ }
+ if (verbose)
+ args << "-v"
+
+ def fp = fregePaths
+ if (!fp.isEmpty()) {
+ args << "-fp"
+ args << fp.collect { f -> f.absolutePath }.join(File.pathSeparator)
+ }
+
+ if (sourcePaths != null && !sourcePaths.isEmpty()) {
+ args << "-sp"
+ args << sourcePaths.collect { d -> d.absolutePath }.join(File.pathSeparator)
+ }
+
+ if (encoding != "") {
+ args << "-enc"
+ args << encoding
+ }
+
+ if (prefix != "") {
+ args << "-prefix"
+ args << prefix
+ }
+
+ args << "-d"
+ args << getDestinationDir()
+
+ if (!module.isEmpty()) {
+ logger.info "compiling module '$module'"
+ args << module
+ } else {
+ args = (args + extraArgs.split().toList()).toList()
+ }
+
+ args
+ }
+
+}
diff --git a/src/main/groovy/frege/gradle/DocTask.groovy b/src/main/groovy/frege/gradle/tasks/FregeDoc.groovy
index 061ae00..7ac49a7 100644
--- a/src/main/groovy/frege/gradle/DocTask.groovy
+++ b/src/main/groovy/frege/gradle/tasks/FregeDoc.groovy
@@ -1,4 +1,4 @@
-package frege.gradle
+package frege.gradle.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.internal.file.FileResolver
@@ -10,7 +10,7 @@ import org.gradle.api.tasks.TaskAction
import org.gradle.process.internal.DefaultJavaExecAction
import org.gradle.process.internal.JavaExecAction
-class DocTask extends DefaultTask {
+class FregeDoc extends DefaultTask {
/* Usage: java -jar fregec.jar frege.tools.Doc [-v] [-d opt] [-x mod,...] modules ...
* -v print a message for each processed module
diff --git a/src/main/groovy/frege/gradle/NativeGenTask.groovy b/src/main/groovy/frege/gradle/tasks/FregeNativeGen.groovy
index c9128ca..6f51218 100644
--- a/src/main/groovy/frege/gradle/NativeGenTask.groovy
+++ b/src/main/groovy/frege/gradle/tasks/FregeNativeGen.groovy
@@ -1,4 +1,4 @@
-package frege.gradle
+package frege.gradle.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.internal.file.FileResolver
@@ -11,7 +11,7 @@ import org.gradle.api.tasks.TaskAction
import org.gradle.process.internal.DefaultJavaExecAction
import org.gradle.process.internal.JavaExecAction
-class NativeGenTask extends DefaultTask {
+class FregeNativeGen extends DefaultTask {
/*
* Example from https://github.com/Frege/frege-native-gen:
diff --git a/src/main/groovy/frege/gradle/QuickCheckTask.groovy b/src/main/groovy/frege/gradle/tasks/FregeQuickCheck.groovy
index 11065ad..e06236f 100644
--- a/src/main/groovy/frege/gradle/QuickCheckTask.groovy
+++ b/src/main/groovy/frege/gradle/tasks/FregeQuickCheck.groovy
@@ -1,15 +1,11 @@
-package frege.gradle
-
+package frege.gradle.tasks
import org.gradle.api.DefaultTask
-import org.gradle.api.Project
import org.gradle.api.internal.file.FileResolver
-import org.gradle.api.tasks.InputDirectory
-import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction
import org.gradle.process.internal.DefaultJavaExecAction
import org.gradle.process.internal.JavaExecAction
-class QuickCheckTask extends DefaultTask {
+class FregeQuickCheck extends DefaultTask {
// more options to consider:
/*
diff --git a/src/main/groovy/frege/gradle/ReplTask.groovy b/src/main/groovy/frege/gradle/tasks/FregeRepl.groovy
index 1f570eb..64e0186 100644
--- a/src/main/groovy/frege/gradle/ReplTask.groovy
+++ b/src/main/groovy/frege/gradle/tasks/FregeRepl.groovy
@@ -1,4 +1,4 @@
-package frege.gradle
+package frege.gradle.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.internal.file.FileResolver
@@ -6,7 +6,7 @@ import org.gradle.api.tasks.*
import org.gradle.process.internal.DefaultJavaExecAction
import org.gradle.process.internal.JavaExecAction
-class ReplTask extends DefaultTask {
+class FregeRepl extends DefaultTask {
static String DEFAULT_SRC_DIR = "src/main/frege" // TODO: should this come from a source set?
static String DEFAULT_CLASSES_SUBDIR = "classes/main" // TODO: should this come from a convention?
diff --git a/src/main/resources/META-INF/gradle-plugins/org.frege-lang.base.properties b/src/main/resources/META-INF/gradle-plugins/org.frege-lang.base.properties
new file mode 100644
index 0000000..50f947e
--- /dev/null
+++ b/src/main/resources/META-INF/gradle-plugins/org.frege-lang.base.properties
@@ -0,0 +1 @@
+implementation-class=frege.gradle.plugins.FregeBasePlugin
diff --git a/src/main/resources/META-INF/gradle-plugins/org.frege-lang.properties b/src/main/resources/META-INF/gradle-plugins/org.frege-lang.properties
index 25a44ac..db20350 100644
--- a/src/main/resources/META-INF/gradle-plugins/org.frege-lang.properties
+++ b/src/main/resources/META-INF/gradle-plugins/org.frege-lang.properties
@@ -1 +1 @@
-implementation-class=frege.gradle.FregePlugin
+implementation-class=frege.gradle.plugins.FregePlugin
diff --git a/src/test/groovy/frege/gradle/FregeBasePluginTest.groovy b/src/test/groovy/frege/gradle/FregeBasePluginTest.groovy
new file mode 100644
index 0000000..3ca1bb2
--- /dev/null
+++ b/src/test/groovy/frege/gradle/FregeBasePluginTest.groovy
@@ -0,0 +1,31 @@
+package frege.gradle
+
+import frege.gradle.plugins.FregeBasePlugin
+import org.gradle.api.Project
+import org.gradle.testfixtures.ProjectBuilder
+import spock.lang.Specification
+
+public class FregeBasePluginTest extends Specification {
+
+ Project project = ProjectBuilder.builder().build()
+
+ def setup(){
+ when:
+ project.plugins.apply(FregeBasePlugin)
+ }
+
+ def "adds frege extension"(){
+ expect:
+ project.getExtensions().getByName(FregeBasePlugin.EXTENSION_NAME) != null
+ }
+
+ def "applies java base plugin"(){
+ expect:
+ project.pluginManager.hasPlugin("java-base")
+ }
+
+ def "can be identified by id"(){
+ expect:
+ project.pluginManager.hasPlugin("org.frege-lang.base")
+ }
+} \ No newline at end of file
diff --git a/src/test/groovy/frege/gradle/FregePluginTest.groovy b/src/test/groovy/frege/gradle/FregePluginTest.groovy
new file mode 100644
index 0000000..2fc6d86
--- /dev/null
+++ b/src/test/groovy/frege/gradle/FregePluginTest.groovy
@@ -0,0 +1,32 @@
+package frege.gradle
+
+import frege.gradle.plugins.FregeBasePlugin
+import frege.gradle.plugins.FregePlugin
+import org.gradle.api.Project
+import org.gradle.testfixtures.ProjectBuilder
+import spock.lang.Specification
+
+class FregePluginTest extends Specification {
+
+ Project project = ProjectBuilder.builder().build()
+
+ def setup(){
+ when:
+ project.plugins.apply(FregePlugin)
+ }
+
+ def "adds frege extension"(){
+ expect:
+ project.getExtensions().getByName(FregeBasePlugin.EXTENSION_NAME) != null
+ }
+
+ def "applies frege base plugin"() {
+ expect:
+ project.pluginManager.findPlugin("org.frege-lang.base") != null
+ }
+
+ def "can be identified by id"(){
+ expect:
+ project.pluginManager.hasPlugin("org.frege-lang")
+ }
+}