From 2a927d38d72eb54bcd6d0e742952d25894c75008 Mon Sep 17 00:00:00 2001 From: Marharyta Date: Thu, 13 Jul 2023 18:02:52 +0200 Subject: [PATCH] SONARGRADL-120 Add .gradle.kts files to the sonar.sources (#182) --- .../gradle/SonarPropertyComputer.java | 31 ++- .../sonarqube/gradle/GradleKtsTests.groovy | 202 ++++++++++++++++++ 2 files changed, 229 insertions(+), 4 deletions(-) create mode 100644 src/test/groovy/org/sonarqube/gradle/GradleKtsTests.groovy diff --git a/src/main/java/org/sonarqube/gradle/SonarPropertyComputer.java b/src/main/java/org/sonarqube/gradle/SonarPropertyComputer.java index dd647c98..19951465 100644 --- a/src/main/java/org/sonarqube/gradle/SonarPropertyComputer.java +++ b/src/main/java/org/sonarqube/gradle/SonarPropertyComputer.java @@ -50,6 +50,7 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -225,10 +226,14 @@ private static void configureForJava(final Project project, final Map properties, Object kotlinProjectExtension) { Collection sourceDirectories = getKotlinSourceFiles(kotlinProjectExtension, MAIN_SOURCE_SET_SUFFIX); - properties.put(SONAR_SOURCES_PROP, sourceDirectories); + if (sourceDirectories != null) { + SonarUtils.appendProps(properties, SONAR_SOURCES_PROP, sourceDirectories); + } Collection testDirectories = getKotlinSourceFiles(kotlinProjectExtension, TEST_SOURCE_SET_SUFFIX); - properties.put(SONAR_TESTS_PROP, testDirectories); + if (testDirectories != null) { + SonarUtils.appendProps(properties, SONAR_TESTS_PROP, testDirectories); + } if (sourceDirectories != null || testDirectories != null) { configureSourceEncoding(project, properties); @@ -308,11 +313,15 @@ private static void configureSourceDirsAndJavaClasspath(Project project, Map sourceDirectories = getJavaSourceFiles(main); - properties.put(SONAR_SOURCES_PROP, sourceDirectories); + if (sourceDirectories != null) { + SonarUtils.appendProps(properties, SONAR_SOURCES_PROP, sourceDirectories); + } SourceSet test = javaPluginConvention.getSourceSets().getAt("test"); Collection testDirectories = getJavaSourceFiles(test); - properties.put(SONAR_TESTS_PROP, testDirectories); + if (testDirectories != null) { + SonarUtils.appendProps(properties, SONAR_TESTS_PROP, testDirectories); + } if (sourceDirectories != null || testDirectories != null) { configureSourceEncoding(project, properties); @@ -443,6 +452,8 @@ private void addGradleDefaults(final Project project, final Map properties.put("sonar.projectBaseDir", project.getProjectDir()); properties.put("sonar.kotlin.gradleProjectRoot", project.getRootProject().getProjectDir().getAbsolutePath()); + addKotlinBuildScriptsToSources(project, properties); + if (project.equals(targetProject)) { // Root project of the analysis properties.put("sonar.working.directory", new File(project.getBuildDir(), "sonar")); @@ -459,6 +470,18 @@ private void addGradleDefaults(final Project project, final Map } } + private static void addKotlinBuildScriptsToSources(Project project, Map properties) { + List buildScripts = project.getAllprojects().stream() + .map(Project::getBuildFile) + .filter(file -> file.getAbsolutePath().endsWith("kts")) + .collect(Collectors.toList()); + + var settingsFile = Path.of(project.getProjectDir().getAbsolutePath(), "settings.gradle.kts").toFile(); + if (settingsFile.exists()) buildScripts.add(settingsFile); + + if (!buildScripts.isEmpty()) SonarUtils.appendProps(properties, SONAR_SOURCES_PROP, buildScripts); + } + private String computeProjectKey() { Project rootProject = targetProject.getRootProject(); String rootProjectName = rootProject.getName(); diff --git a/src/test/groovy/org/sonarqube/gradle/GradleKtsTests.groovy b/src/test/groovy/org/sonarqube/gradle/GradleKtsTests.groovy new file mode 100644 index 00000000..3c28d0ec --- /dev/null +++ b/src/test/groovy/org/sonarqube/gradle/GradleKtsTests.groovy @@ -0,0 +1,202 @@ +/* + * SonarQube Scanner for Gradle + * Copyright (C) 2015-2023 SonarSource + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonarqube.gradle + +import org.assertj.core.api.Assertions +import org.gradle.testkit.runner.GradleRunner +import spock.lang.Specification +import spock.lang.TempDir + +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.StandardCopyOption + +class GradleKtsTests extends Specification { + @TempDir + Path testProjectDir + Path settingsFile + Path buildFile + Path outFile + + def setup() { + outFile = testProjectDir.resolve('out.properties') + // For JaCoCo coverage, see https://github.com/koral--/jacoco-gradle-testkit-plugin + InputStream is = GradleKtsTests.class.getClassLoader().getResourceAsStream('testkit-gradle.properties') + Files.copy(is, testProjectDir.resolve('gradle.properties'), StandardCopyOption.REPLACE_EXISTING) + } + + def "add build and settings gradle files to sources when both are in kotlin dsl"() { + given: + addBuildKts() + addSettingsKts() + + when: + def result = GradleRunner.create() + .withProjectDir(testProjectDir.toFile()) + .forwardOutput() + .withArguments('sonarqube', '--info', '-Dsonar.scanner.dumpToFile=' + outFile.toAbsolutePath()) + .withPluginClasspath() + .build() + + def props = new Properties() + props.load(outFile.newDataInputStream()) + + then: + def sonarSources = props["sonar.sources"].split(",") + Assertions.assertThat(sonarSources) + .containsExactlyInAnyOrder(settingsFile.toRealPath().toString(), buildFile.toRealPath().toString()) + + } + + def "add only build and file to sources when only build is in kotlin dsl"() { + given: + addBuildKts() + addSettings() + + when: + def result = GradleRunner.create() + .withProjectDir(testProjectDir.toFile()) + .forwardOutput() + .withArguments('sonarqube', '--info', '-Dsonar.scanner.dumpToFile=' + outFile.toAbsolutePath()) + .withPluginClasspath() + .build() + + def props = new Properties() + props.load(outFile.newDataInputStream()) + + then: + props["sonar.sources"] == buildFile.toRealPath().toString() + + } + + def "add only settings file to sources when only settings file is in kotlin dsl"() { + given: + addBuild() + addSettingsKts() + + when: + def result = GradleRunner.create() + .withProjectDir(testProjectDir.toFile()) + .forwardOutput() + .withArguments('sonarqube', '--info', '-Dsonar.scanner.dumpToFile=' + outFile.toAbsolutePath()) + .withPluginClasspath() + .build() + + def props = new Properties() + props.load(outFile.newDataInputStream()) + + then: + props["sonar.sources"] == settingsFile.toRealPath().toString() + + } + + def "add only build file to sources when no settings found"() { + given: + addBuildKts() + + when: + def result = GradleRunner.create() + .withProjectDir(testProjectDir.toFile()) + .forwardOutput() + .withArguments('sonarqube', '--info', '-Dsonar.scanner.dumpToFile=' + outFile.toAbsolutePath()) + .withPluginClasspath() + .build() + + def props = new Properties() + props.load(outFile.newDataInputStream()) + + then: + props["sonar.sources"] == buildFile.toRealPath().toString() + + } + + def "add nothing to sources when Groovy dsl is used"() { + given: + addBuild() + addSettings() + + when: + def result = GradleRunner.create() + .withProjectDir(testProjectDir.toFile()) + .forwardOutput() + .withArguments('sonarqube', '--info', '-Dsonar.scanner.dumpToFile=' + outFile.toAbsolutePath()) + .withPluginClasspath() + .build() + + def props = new Properties() + props.load(outFile.newDataInputStream()) + + then: + props["sonar.sources"] == "" + + } + + def "add nothing to sources when Groovy dsl is used and no settings"() { + given: + addBuild() + + when: + def result = GradleRunner.create() + .withProjectDir(testProjectDir.toFile()) + .forwardOutput() + .withArguments('sonarqube', '--info', '-Dsonar.scanner.dumpToFile=' + outFile.toAbsolutePath()) + .withPluginClasspath() + .build() + + def props = new Properties() + props.load(outFile.newDataInputStream()) + + then: + props["sonar.sources"] == "" + + } + + private def addSettings() { + settingsFile = testProjectDir.resolve('settings.gradle') + settingsFile << "rootProject.name = 'java-task-toolchains'" + } + + private def addSettingsKts() { + settingsFile = testProjectDir.resolve('settings.gradle.kts') + settingsFile << """rootProject.name = "java-task-toolchains" + """ + } + + private def addBuild() { + buildFile = testProjectDir.resolve('build.gradle') + buildFile << """ + plugins { + id 'java' + id 'org.sonarqube' + } + """ + } + + private def addBuildKts() { + buildFile = testProjectDir.resolve('build.gradle.kts') + buildFile << """ + plugins { + java + id("org.sonarqube") + } + """ + } +} +