Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<p align="center">
<a href="https://github.com/AkaZver/mapstruct-plugin/actions"><img src="https://github.com/AkaZver/mapstruct-plugin/workflows/Build/badge.svg" alt="Actions Status"></a>
<a href="#"><img src="https://img.shields.io/maven-metadata/v.svg?metadataUrl=https%3A%2F%2Fplugins.gradle.org%2Fm2%2Fio%2Fgithub%2Fakazver%2Fmapstruct%2Fio.github.akazver.mapstruct.gradle.plugin%2Fmaven-metadata.xml&label=Plugin%20Version&logo=github" alt="Plugin Version"></a>
<a href="https://sonarcloud.io"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=alert_status" alt="Quality Gate Status"></a>
<a href="https://sonarcloud.io"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=coverage" alt="Coverage"></a>
<a href="https://plugins.gradle.org/plugin/io.github.akazver.mapstruct"><img src="https://img.shields.io/maven-metadata/v.svg?metadataUrl=https%3A%2F%2Fplugins.gradle.org%2Fm2%2Fio%2Fgithub%2Fakazver%2Fmapstruct%2Fio.github.akazver.mapstruct.gradle.plugin%2Fmaven-metadata.xml&label=Plugin%20Version&logo=github" alt="Plugin Version"></a>
<a href="https://sonarcloud.io/project/overview?id=AkaZver_mapstruct-plugin"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=alert_status" alt="Quality Gate Status"></a>
<a href="https://sonarcloud.io/project/overview?id=AkaZver_mapstruct-plugin"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=coverage" alt="Coverage"></a>
<br/>
<a href="https://sonarcloud.io"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=security_rating" alt="Security Rating"></a>
<a href="https://sonarcloud.io"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=reliability_rating" alt="Reliability Rating"></a>
<a href="https://sonarcloud.io"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=sqale_rating" alt="Maintainability Rating"></a>
<a href="https://sonarcloud.io"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=vulnerabilities" alt="Vulnerabilities"></a>
<a href="https://sonarcloud.io/project/overview?id=AkaZver_mapstruct-plugin"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=security_rating" alt="Security Rating"></a>
<a href="https://sonarcloud.io/project/overview?id=AkaZver_mapstruct-plugin"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=reliability_rating" alt="Reliability Rating"></a>
<a href="https://sonarcloud.io/project/overview?id=AkaZver_mapstruct-plugin"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=sqale_rating" alt="Maintainability Rating"></a>
<a href="https://sonarcloud.io/project/overview?id=AkaZver_mapstruct-plugin"><img src="https://sonarcloud.io/api/project_badges/measure?project=AkaZver_mapstruct-plugin&metric=vulnerabilities" alt="Vulnerabilities"></a>
<br/>
<a href="#"><img src="https://img.shields.io/badge/Java-17-blue.svg?logo=intellijidea" alt="Java"></a>
<a href="#"><img src="https://img.shields.io/badge/Gradle-9.6.1-blue.svg?logo=gradle" alt="Gradle"></a>
Expand Down Expand Up @@ -39,6 +39,7 @@ The plugin automatically:
- Adds MapStruct dependencies (`mapstruct` and `mapstruct-processor`)
- Detects optional dependencies (Lombok, Spring, Camel, Quarkus, Protobuf) in your project
- Adds required binding libraries when needed (e.g., `lombok-mapstruct-binding` for Lombok)
- Detects Kotlin and automatically applies `kapt` plugin with proper configuration
- Configures compiler arguments based on your `mapstruct {}` block settings
- Runs after project evaluation to ensure all dependencies are resolved

Expand Down
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
plugins {
id 'com.vanniktech.maven.publish' version '0.37.0'
id 'com.gradle.plugin-publish' version '2.1.1'
id 'io.freefair.lombok' version '9.5.0'
id 'org.sonarqube' version '7.3.1.8318'
id 'com.vanniktech.maven.publish' version '0.37.0'
id 'java-gradle-plugin'
id 'jacoco'
}
Expand Down Expand Up @@ -40,6 +40,8 @@ dependencies {
testImplementation 'org.springframework.boot:org.springframework.boot.gradle.plugin:4.1.0'
// id 'com.google.protobuf' version '0.10.0'
testImplementation 'com.google.protobuf:com.google.protobuf.gradle.plugin:0.10.0'
// id 'org.jetbrains.kotlin.jvm' version '2.0.21'
testImplementation 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21'

testImplementation 'org.assertj:assertj-core:3.27.7'
testImplementation 'org.junit.jupiter:junit-jupiter:6.1.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ public void apply(@NotNull Project project) {
project.getExtensions().create("mapstruct", MapstructExtension.class);

project.afterEvaluate(it -> {
dependencyManager.addRequiredDependencies();
dependencyManager.addOptionalDependencies();
dependencyManager.addDependencies();
compilerArgsManager.addCompilerArgs();
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.plugins.ExtensionContainer;
import org.gradle.api.plugins.PluginManager;

import static io.github.akazver.gradle.plugins.mapstruct.dependency.AdditionalDependency.*;
import static io.github.akazver.gradle.plugins.mapstruct.dependency.MarkerDependency.*;
Expand All @@ -27,19 +28,34 @@ public class DependencyManager {
private final ConfigurationContainer configurations;
private final ExtensionContainer extensions;
private final DependencyHandler dependencies;
private final PluginManager pluginManager;

public DependencyManager(Project project) {
this.configurations = project.getConfigurations();
this.extensions = project.getExtensions();
this.dependencies = project.getDependencies();
this.pluginManager = project.getPluginManager();
}

public void addRequiredDependencies() {
public void addDependencies() {
boolean hasKotlin = hasExtension("kotlin");
String processorConfig = hasKotlin ? "kapt" : "annotationProcessor";

if (hasKotlin) {
pluginManager.apply("org.jetbrains.kotlin.kapt");
}

addRequiredDependencies(processorConfig);
addOptionalDependencies(processorConfig);
}

private void addRequiredDependencies(String processorConfig) {
LOGGER.lifecycle(ADDING_MESSAGE, "MapStruct");
addDependencies(MAPSTRUCT, MAPSTRUCT_PROCESSOR);
addDependency(MAPSTRUCT);
addDependency(MAPSTRUCT_PROCESSOR, processorConfig);
}

public void addOptionalDependencies() {
private void addOptionalDependencies(String processorConfig) {
boolean hasLombok = hasExtension("lombok") || hasDependency(LOMBOK);
boolean hasBinding = hasDependency(LOMBOK_MAPSTRUCT_BINDING);
boolean hasSpringBoot = hasExtension("springBoot") || hasDependency(SPRING_BOOT);
Expand All @@ -50,12 +66,14 @@ public void addOptionalDependencies() {

if (hasLombok && !hasBinding) {
LOGGER.lifecycle(ADDING_MESSAGE, "Lombok");
addDependency(LOMBOK_MAPSTRUCT_BINDING);
addDependency(LOMBOK_MAPSTRUCT_BINDING, processorConfig);
}

if (hasSpringBoot || hasSpring) {
LOGGER.lifecycle(ADDING_MESSAGE, "Spring");
addDependencies(MAPSTRUCT_SPRING_EXTENSIONS, MAPSTRUCT_SPRING_ANNOTATIONS, MAPSTRUCT_SPRING_TEST_EXTENSIONS);
addDependency(MAPSTRUCT_SPRING_EXTENSIONS, processorConfig);
addDependency(MAPSTRUCT_SPRING_ANNOTATIONS);
addDependency(MAPSTRUCT_SPRING_TEST_EXTENSIONS);
}

if (hasCamel) {
Expand Down Expand Up @@ -97,15 +115,13 @@ private boolean hasExtension(String extensionName) {
return extensions.findByName(extensionName) != null;
}

private void addDependency(PluginDependency pluginDependency) {
private void addDependency(PluginDependency pluginDependency, String configuration) {
LOGGER.lifecycle(DEPENDENCY_PREFIX, pluginDependency.getId());
dependencies.add(pluginDependency.getConfiguration(), pluginDependency.getId());
dependencies.add(configuration, pluginDependency.getId());
}

private void addDependencies(PluginDependency... pluginDependencies) {
for (PluginDependency pluginDependency : pluginDependencies) {
addDependency(pluginDependency);
}
private void addDependency(PluginDependency pluginDependency) {
addDependency(pluginDependency, pluginDependency.getConfiguration());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.DependencySet;
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.gradle.plugin.SpringBootPlugin;
Expand Down Expand Up @@ -303,6 +304,63 @@ void addOptionalDependenciesWithProtobufPlugin() {
optionalDependenciesWithoutSpringTest(project, expectedAnnotationProcessor, expectedImplementation);
}

@Test
@DisplayName("Add dependencies with Kotlin plugin")
void addDependenciesWithKotlinPlugin() {
Project project = fetchBaseProject();
project.getPluginManager().apply(KotlinPluginWrapper.class);
evaluate(project);

assertThat(project.getPlugins().findPlugin("org.jetbrains.kotlin.jvm")).isNotNull();
assertThat(project.getPlugins().findPlugin("org.jetbrains.kotlin.kapt")).isNotNull();

assertThat(fetchDependencyIds(project, "kapt"))
.hasSize(1)
.first()
.isEqualTo(MAPSTRUCT_PROCESSOR.getId());

assertThat(fetchDependencyIds(project, "implementation"))
.hasSize(1)
.first()
.isEqualTo(MAPSTRUCT.getId());

assertThat(fetchDependencyIds(project, "annotationProcessor"))
.isEmpty();
}

@Test
@DisplayName("Add dependencies with Kotlin plugin and Spring")
void addDependenciesWithKotlinPluginAndSpring() {
Project project = fetchBaseProject();
project.getPluginManager().apply(KotlinPluginWrapper.class);
project.getDependencies().add(SPRING_CORE.getConfiguration(), SPRING_CORE.getId());
evaluate(project);

assertThat(project.getPlugins().findPlugin("org.jetbrains.kotlin.jvm")).isNotNull();
assertThat(project.getPlugins().findPlugin("org.jetbrains.kotlin.kapt")).isNotNull();

String[] expectedKapt = {
MAPSTRUCT_PROCESSOR.getId(),
MAPSTRUCT_SPRING_EXTENSIONS.getId()
};

String[] expectedImplementation = {
SPRING_CORE.getId(), MAPSTRUCT.getId(),
MAPSTRUCT_SPRING_ANNOTATIONS.getId()
};

assertThat(fetchDependencyIds(project, "kapt"))
.hasSize(expectedKapt.length)
.containsExactlyInAnyOrder(expectedKapt);

assertThat(fetchDependencyIds(project, "implementation"))
.hasSize(expectedImplementation.length)
.containsExactlyInAnyOrder(expectedImplementation);

assertThat(fetchDependencyIds(project, "annotationProcessor"))
.isEmpty();
}

private void optionalDependenciesTest(Project project, String[] expectedAnnotationProcessor, String[] expectedImplementation) {
String[] expectedTestImplementation =
Stream.concat(Arrays.stream(expectedImplementation), Stream.of(MAPSTRUCT_SPRING_TEST_EXTENSIONS.getId()))
Expand Down