Converting SourceSet definition in plugin from Groovy DSL to Kotlin DSL - gradle

I've got a method in my Gradle plugin which declares a new "scratch" source set. I'm trying to convert this method from Groovy to Kotlin, but I cannot figure out how I'm meant to declare the new SourceSet using Kotlin.
class JavaConventionsPlugin : Plugin<Project> {
// ...
def scratchConfiguration(project) {
project.sourceSets {
scratch {
}
}
project.configurations {
// make scratch configurations include all normal dependencies automatically
scratchCompile.extendsFrom mainCompile
scratchRuntime.extendsFrom mainRuntime
scratchCompileOnly.extendsFrom compileOnly
scratchImplementation.extendsFrom implementation
scratchRuntimeOnly.extendsFrom runtimeOnly
}
project.dependencies {
// add dependency on main java code from scratch java code
scratchImplementation project.extensions.getByType(JavaPluginExtension).sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).output
}
}
}
Within the converted scratchConfiguration method, all of these seem to be unresolved references:
sourceSets
project.sourceSets
java.sourceSets
So what should the new SourceSet declaration look like?

They are unresolved because you are moving from a weakly typed/dynamic language (Groovy) to a strongly typed one (Kotlin). At its core, Gradle is written in plain Java. So, you need to make use of the Java APIs instead of the syntactic sugar that the Groovy DSL had provided.
Your snippet above would moreorless translate to the following:
import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer
class ScratchGradlePlugin: Plugin<Project> {
override fun apply(project: Project) {
val sourceSets = project.extensions.getByType(SourceSetContainer::class.java)
val main = sourceSets.named(SourceSet.MAIN_SOURCE_SET_NAME)
sourceSets.register("scratch") {
it.compileClasspath.plus(main.get().output)
it.runtimeClasspath.plus(main.get().output)
}
val configurations = project.configurations
configurations.named("scratchImplementation") {
it.extendsFrom(configurations.named(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME).get())
}
configurations.named("scratchRuntimeOnly") {
it.extendsFrom(configurations.named(JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME).get())
}
}
}
I have omitted the project.dependencies {} part in your snippet since the sample above has scratch extend from main which is your main Java code.
Ref: https://docs.gradle.org/current/userguide/java_gradle_plugin.html#java_gradle_plugin

Related

gradle testFixturesImplementation cannot find symbol Mockito

I am trying to set up testFixtures. I have a class that until now was in src/test/ and now I'm trying to turn it into fixrure.
In build.gradle I added:
plugins {
id 'java-library'
id "java-test-fixtures"
}
I moved the class from src/test/java/com/example/AmazonTestConfig.java to src/testFixtures/java/com/example/AmazonTestConfig.java
And in the dependencies I had to add a few things, i.e:
dependencies {
...
testFixturesImplementation project(':MyCommon')
testFixturesImplementation 'com.amazonaws:aws-java-sdk-s3:1.12.75'
testFixturesImplementation 'junit:junit:4.13'
testFixturesImplementation 'org.mockito:mockito-all:1.9.0'
}
The first 3 dependencies work, but the mockito doesn't. Here's part of my Foo.java:
import static org.mockito.Mockito.*;
#Ignore
public interface AmazonTestConfig {
default void setS3FilesDal(ServerEngine engineMock) {
ICloudStorage s3FilesDal = new AWSStorage();
CloudServices cloudServicesMock = Mockito.mock(CloudServices.class);
Mockito.when(engineMock.getCloudServices()).thenReturn(cloudServicesMock);
Mockito.when(cloudServicesMock.getStorage()).thenReturn(s3FilesDal);
}
}
But I get the following compilation error:
myproject/src/testFixtures/java/com/example/AmazonTestConfig.java:23: error: cannot find symbol
CloudServices cloudServicesMock = Mockito.mock(CloudServices.class);
^
symbol: variable Mockito
location: interface AmazonTestConfig
I'm not sure why, but changing:
import static org.mockito.Mockito.*;
to:
import org.mockito.Matchers;
import org.mockito.Mockito;
fixed the problem. Looks like a bug in gradle.

IntelliJ UnitTests Kotlin and Java with same name

We have got a project from our university where they have created empty Java and Kotlin classes for us to add our code and some UnitTests to check if we have completed the assignments. I've been put in the Kotlin class and thus have to solve the problems in Kotlin and ignore Java. My problem now is that the UnitTests execute the Java code and not Kotlin.
For example:
Java Class:
package string;
public class Arrow {
public static String arrow(int length, boolean doubleEnded, boolean doubleLine) {
// TODO Implement the method
return "java";
}
}
Kotlin Class:
#file:JvmName("Arrow")
package string
// TODO Implement the function
fun arrow(length: Int, doubleEnded: Boolean, doubleLine: Boolean): String{
return "kotlin";
}
UnitTest and Result:
package string;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class ArrowTest {
static final int NBR_TESTS = 20;
#Test
void arrow0() {
Assertions.assertEquals("", Arrow.arrow(0, true, true));
Assertions.assertEquals("", Arrow.arrow(0, false, true));
Assertions.assertEquals("", Arrow.arrow(0, true, false));
Assertions.assertEquals("", Arrow.arrow(0, false, false));
}
}
org.opentest4j.AssertionFailedError:
Expected :
Actual :java
What do I have to do so that the UnitTests execute the Kotlin code and not Java?
They told us we should not change anything in the tests.
As #user3159253 commented changing the sourceDirectory did it for me.
I opened the module settings and removed Java as a source and added Kotlin.

Unable to resolve class - gradle

I have directory structure as below:
src
--foo
--A.groovy
--test
--groovy
buildTest.groovy
This is the A.groovy class :
package foo
class A {
void execute() {
println "Inside A"
}
}
This my buildTest.groovy
class buildTest {
#Test
void should_execute(){
A a = new A()
def result = a.execute()
}
}
When I run ./gradlew test, it throws error :
Unable to resolve class A
A a = new A()
^
This is my build.gradle :
plugins {
id "groovy"
}
repositories {
mavenCentral()
maven { url 'https://repo.jenkins-ci.org/releases/' }
}
dependencies {
compile 'org.eclipse.hudson:hudson-core:3.2.1'
implementation 'org.codehaus.groovy:groovy-all:3.0.7'
testImplementation 'junit:junit:4.12'
testImplementation "com.lesfurets:jenkins-pipeline-unit:1.3"
}
sourceSets {
main {
groovy {
srcDirs = ['src/foo']
}
}
}
Could someone help me in resolving this error.
You have declared a class A in package foo. (Note that the layout doesn't reflect this as the file should be in src/foo/foo/A.groovy, although Groovy doesn't really care).
However, the test class is not in a package and therefore can't see foo.A. Either import it or move the test class to package foo as well. Alternatively, remove the package declaration from class A, though I don't think that is good practice.
I also agree with the comment about not changing the layout unless you have a very good reason for it (e.g. you are working on a legacy project). This is probably what has caused confusion about what package the class is actually in.

Gradle error: Could not find method jar() for arguments

I'm writing a custom plugin which adds some data to manifest of Java project.
It looks something like this:
package com.example.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
public class ExamplePlugin implements Plugin<Project> {
def apply(Project project) {
project.jar() {
manifest {
attributes 'buildServer': checkIfIsBuildServer()
attributes 'personalBuild': checkIfIsPersonalBuild()
}
}
}
def checkIfIsBuildServer() {
return 'some result'
}
def checkIfIsPersonalBuild() {
return 'some result'
}
}
When I'm trying to apply it to some project, I get an error:
Could not find method jar() for arguments [com.example.gradle.ExamplePlugin$_apply_closure1#411e4f5e] on project ':SomeProject' of type org.gradle.api.Project.
I am reasonably sure this is some missing import. I don't have any idea how to determine what import it should be.
jar() isn’t a method on Project.
If I’m understanding your code correctly, what you are trying to do is configure the jar task that is created from the Java Plugin.
So you need to:
Get the task
Configure the task
Something like:
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Jar
public class ExamplePlugin implements Plugin<Project> {
def apply(Project project) {
project.afterEvaluate {
project.tasks.named(JavaPlugin.JAR_TASK_NAME, Jar) {
it.manifest {
attributes 'buildServer': checkIfIsBuildServer()
attributes 'personalBuild': checkIfIsPersonalBuild()
}
}
}
}
def checkIfIsBuildServer() {
'some result'
}
def checkIfIsPersonalBuild() {
'some result'
}
}
I highly recommend switch to Kotlin or Java for your plugin. It will make errors like this trivial to resolve and you will fully understand where things are coming from compared to Groovy’s dynamic nature.

Gradle plugin for custom language

I have a custom language (let's say it is MyLang but it can be any language) and I would like to make a plugin for it. The plugin needs to
be able to recognize the sourcesets for the language given with DSL
be able to compile them using an executable (the compiler)
I was able to create a plugin with a compile task (empty yet) and annotate a function with #LanguageType setting the language name to "mylang".
How can I modify the plugin to be possible to add sourcesets from build.gradle files using DSL like sourceSets { mylang { ... } }?
How can I modify the build task to be able to build the files of the source set?
class MylangBuildPlugin implements Plugin<Project> {
static final String COMPILE_TASK_NAME = 'compileMylang'
void apply(Project project) {
project.getPluginManager().apply(ComponentModelBasePlugin.class);
createCompileTask(project)
}
#LanguageType
void registerLanguage(LanguageTypeBuilder<BaseLanguageSourceSet> builder) {
builder.setLanguageName("mylang");
builder.defaultImplementation(BaseLanguageSourceSet.class);
}
private void createCompileTask(Project project) {
project.task(COMPILE_TASK_NAME) {
}
}
}

Resources