From: Julien HENRY Date: Mon, 11 Feb 2019 16:14:32 +0000 (+0100) Subject: SONAR-11558 Index basedir by default when sonar.sources is not provided X-Git-Tag: 7.7~138 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=aaf851d1f104a7493e2db9d15a1d77652f6804c0;p=sonarqube.git SONAR-11558 Index basedir by default when sonar.sources is not provided --- diff --git a/server/sonar-docs/src/pages/analysis/analysis-parameters.md b/server/sonar-docs/src/pages/analysis/analysis-parameters.md index 600e9055a5d..ac7f53c577d 100644 --- a/server/sonar-docs/src/pages/analysis/analysis-parameters.md +++ b/server/sonar-docs/src/pages/analysis/analysis-parameters.md @@ -13,7 +13,7 @@ Parameters to configure project analysis can be set in multiple places. Here is * Analysis / Command line parameters, defined when launching an analysis, override project analysis parameters Note that only parameters set through the UI are stored in the database. -For example, if you override the `sonar.exclusions` parameter via command line for a specific project, it will not be stored in the database. Local analyses in Eclipse, for example, would still be executed with the exclusions defined in the UI and therefore stored in the DB. +For example, if you override the `sonar.exclusions` parameter via command line for a specific project, it will not be stored in the database. Analyses in SonarLint with connected mode, for example, would still be executed with the exclusions defined in the UI and therefore stored in the DB. Note also that the list of parameters below is not exhaustive. Most of the property keys shown in the interface, at both global and project levels, can also be set as analysis parameters. However, exclusions/inclusions are far easier to manage in the UI. @@ -29,15 +29,14 @@ Key | Description | Default ### Project Configuration Key | Description | Default ---|----|--- -`sonar.projectKey`|The project's unique key. Allowed characters are: letters, numbers, `-`, `_`, `.` and `:`, with at least one non-digit. | For Maven projects, this is automatically set to `:` -`sonar.sources` | Comma-separated paths to directories containing source files. | Read from build system for Maven, Gradle, MSBuild projects +`sonar.projectKey`|The project's unique key. Allowed characters are: letters, numbers, `-`, `_`, `.` and `:`, with at least one non-digit. | For Maven projects, this defaults to `:` ## Optional Parameters ### Project Identity Key | Description | Default ---|----|--- -`sonar.projectName`|Name of the project that will be displayed on the web interface.|`` for Maven projects, otherwise project key. If there is already a name in the DB, it won't be overwritten +`sonar.projectName`|Name of the project that will be displayed on the web interface.|`` for Maven projects, otherwise project key. If not provided and there is already a name in the DB, it won't be overwritten `sonar.projectVersion` | The project version. | `` for Maven projects, otherwise "not provided" ### Authentication @@ -57,13 +56,14 @@ Key | Description | Default ### Project Configuration Key | Description | Default ---|----|--- -`sonar.projectDescription` | The project description. Not compatible with Maven. | `` for Maven projects -`sonar.links.homepage` | Project home page. Not compatible with Maven. | `` for Maven projects -`sonar.links.ci` | Continuous integration. Not compatible with Maven. | `` for Maven projects -`sonar.links.issue` | Issue tracker. Not compatible with Maven. | `` for Maven projects -`sonar.links.scm` | Project source repository. Not compatible with Maven. | `` for Maven projects -`sonar.links.scm_dev` | Developer connection. Not compatible with Maven. | `` for Maven projects -`sonar.tests` | Comma-separated paths to directories containing tests. Not compatible with Maven. | Default tests location for Java Maven projects. +`sonar.projectDescription` | The project description. | `` for Maven projects +`sonar.links.homepage` | Project home page. | `` for Maven projects +`sonar.links.ci` | Continuous integration. | `` for Maven projects +`sonar.links.issue` | Issue tracker. | `` for Maven projects +`sonar.links.scm` | Project source repository. | `` for Maven projects +`sonar.links.scm_dev` | Developer connection. | `` for Maven projects +`sonar.sources` | Comma-separated paths to directories containing main source files. | Read from build system for Maven, Gradle, MSBuild projects. Defaults to project base directory when neither `sonar.sources` nor `sonar.tests` is provided. +`sonar.tests` | Comma-separated paths to directories containing test source files. | Read from build system for Maven, Gradle, MSBuild projects. Else default to empty. `sonar.sourceEncoding` | Encoding of the source files. Ex: `UTF-8`, `MacRoman`, `Shift_JIS`. This property can be replaced by the standard property `project.build.sourceEncoding` in Maven projects. The list of available encodings depends on your JVM. | System encoding `sonar.externalIssuesReportPaths` | Comma-delimited list of paths to Generic Issue reports. | `sonar.projectDate` | Assign a date to the analysis. This parameter is only useful when you need to retroactively create the history of a not-analyzed-before project. The format is `yyyy-MM-dd`, for example: 2010-12-01. Since you cannot perform an analysis dated prior to the most recent one in the database, you must analyze recreate your project history in chronological order, oldest first. ![](/images/exclamation.svg) Note: You may need to adjust your housekeeping settings if you wish to create a long-running history. | Current date diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java index cad32b8d980..2dbdd8d2fb0 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java @@ -21,7 +21,7 @@ package org.sonar.api.batch.bootstrap; import java.io.File; import java.util.ArrayList; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -53,7 +53,7 @@ public class ProjectDefinition { private File baseDir; private File workDir; private File buildDir; - private Map properties = new HashMap<>(); + private Map properties = new LinkedHashMap<>(); private ProjectDefinition parent = null; private List subProjects = new ArrayList<>(); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java index 06213be6abb..73fa8dd7629 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java @@ -23,6 +23,8 @@ import java.io.File; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Optional; +import javax.annotation.CheckForNull; import javax.annotation.concurrent.Immutable; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.InputModule; @@ -50,7 +52,11 @@ public class DefaultInputModule extends AbstractProjectOrModule implements Input this.testDirsOrFiles = initSources(definition, ProjectDefinition.TESTS_PROPERTY); } + @CheckForNull private List initSources(ProjectDefinition module, String propertyKey) { + if (!module.properties().containsKey(propertyKey)) { + return null; + } List result = new ArrayList<>(); PathResolver pathResolver = new PathResolver(); String srcPropValue = module.properties().get(propertyKey); @@ -65,11 +71,11 @@ public class DefaultInputModule extends AbstractProjectOrModule implements Input return result; } - public List getSourceDirsOrFiles() { - return sourceDirsOrFiles; + public Optional> getSourceDirsOrFiles() { + return Optional.ofNullable(sourceDirsOrFiles); } - public List getTestDirsOrFiles() { - return testDirsOrFiles; + public Optional> getTestDirsOrFiles() { + return Optional.ofNullable(testDirsOrFiles); } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputModuleTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputModuleTest.java index 30eaf20f736..42394d7f81e 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputModuleTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputModuleTest.java @@ -61,8 +61,36 @@ public class DefaultInputModuleTest { assertThat(module.getKeyWithBranch()).isEqualTo("moduleKey"); assertThat(module.getWorkDir()).isEqualTo(workDir.toPath()); assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset()); - assertThat(module.getSourceDirsOrFiles()).containsExactlyInAnyOrder(src); - assertThat(module.getTestDirsOrFiles()).containsExactlyInAnyOrder(test); + assertThat(module.getSourceDirsOrFiles().get()).containsExactlyInAnyOrder(src); + assertThat(module.getTestDirsOrFiles().get()).containsExactlyInAnyOrder(test); + assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset()); + + assertThat(module.isFile()).isFalse(); + } + + @Test + public void no_sources() throws IOException { + ProjectDefinition def = ProjectDefinition.create(); + def.setKey("moduleKey"); + File baseDir = temp.newFolder(); + Path src = baseDir.toPath().resolve(FILE_1); + Files.createFile(src); + Path test = baseDir.toPath().resolve(TEST_1); + Files.createFile(test); + def.setBaseDir(baseDir); + File workDir = temp.newFolder(); + def.setWorkDir(workDir); + DefaultInputModule module = new DefaultInputModule(def); + + assertThat(module.key()).isEqualTo("moduleKey"); + assertThat(module.definition()).isEqualTo(def); + assertThat(module.getBranch()).isNull(); + assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath()); + assertThat(module.getKeyWithBranch()).isEqualTo("moduleKey"); + assertThat(module.getWorkDir()).isEqualTo(workDir.toPath()); + assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset()); + assertThat(module.getSourceDirsOrFiles()).isNotPresent(); + assertThat(module.getTestDirsOrFiles()).isNotPresent(); assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset()); assertThat(module.isFile()).isFalse(); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorBuilder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorBuilder.java index 5f709ee61c7..6b4b9a79677 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorBuilder.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorBuilder.java @@ -88,7 +88,7 @@ public class ProjectReactorBuilder { * Array of all mandatory properties required for a project without child. */ private static final String[] MANDATORY_PROPERTIES_FOR_SIMPLE_PROJECT = { - PROPERTY_PROJECT_BASEDIR, CoreProperties.PROJECT_KEY_PROPERTY, PROPERTY_SOURCES + PROPERTY_PROJECT_BASEDIR, CoreProperties.PROJECT_KEY_PROPERTY }; /** diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java index 85dd31eb3ec..2a60b91322a 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java @@ -53,6 +53,9 @@ import org.sonar.scanner.scan.ProjectServerSettings; import org.sonar.scanner.scm.ScmConfiguration; import org.sonar.scanner.util.ProgressReport; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + /** * Index project input files into {@link InputComponentStore}. */ @@ -143,13 +146,18 @@ public class ProjectFileIndexer { if (componentStore.allModules().size() > 1) { LOG.info("Indexing files of module '{}'", module.getName()); LOG.info(" Base dir: {}", module.getBaseDir().toAbsolutePath()); - logPaths(" Source paths: ", module.getBaseDir(), module.getSourceDirsOrFiles()); - logPaths(" Test paths: ", module.getBaseDir(), module.getTestDirsOrFiles()); + module.getSourceDirsOrFiles().ifPresent(srcs -> logPaths(" Source paths: ", module.getBaseDir(), srcs)); + module.getTestDirsOrFiles().ifPresent(tests -> logPaths(" Test paths: ", module.getBaseDir(), tests)); moduleExclusionFilters.log(" "); moduleCoverageAndDuplicationExclusions.log(" "); } - indexFiles(module, moduleExclusionFilters, moduleCoverageAndDuplicationExclusions, module.getSourceDirsOrFiles(), Type.MAIN, exclusionCounter); - indexFiles(module, moduleExclusionFilters, moduleCoverageAndDuplicationExclusions, module.getTestDirsOrFiles(), Type.TEST, exclusionCounter); + boolean hasChildModules = !module.definition().getSubProjects().isEmpty(); + boolean hasTests = module.getTestDirsOrFiles().isPresent(); + // Default to index basedir when no sources provided + List mainSourceDirsOrFiles = module.getSourceDirsOrFiles() + .orElseGet(() -> hasChildModules || hasTests ? emptyList() : singletonList(module.getBaseDir().toAbsolutePath())); + indexFiles(module, moduleExclusionFilters, moduleCoverageAndDuplicationExclusions, mainSourceDirsOrFiles, Type.MAIN, exclusionCounter); + module.getTestDirsOrFiles().ifPresent(tests -> indexFiles(module, moduleExclusionFilters, moduleCoverageAndDuplicationExclusions, tests, Type.TEST, exclusionCounter)); } private static void logPaths(String label, Path baseDir, List paths) { diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java index a70e2ac2389..dee1c8b1781 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java @@ -1096,4 +1096,18 @@ public class FileSystemMediumTest { assertThat(result.inputFile("xources/hello/ClassOne.xoo")).isNotNull(); assertThat(result.inputFile("testx/ClassOneTest.xoo")).isNotNull(); } + + @Test + public void index_basedir_by_default() throws IOException { + File xooFile = new File(baseDir, "sample.xoo"); + FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + + AnalysisResult result = tester.newAnalysis() + .properties(builder + .build()) + .execute(); + + assertThat(logTester.logs()).contains("1 file indexed"); + assertThat(result.inputFile("sample.xoo")).isNotNull(); + } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorBuilderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorBuilderTest.java index c9bd41df8e7..5e4099793aa 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorBuilderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorBuilderTest.java @@ -77,13 +77,6 @@ public class ProjectReactorBuilderTest { loadProjectDefinition("multi-module-pom-in-root"); } - @Test - public void fail_if_sources_not_set() { - thrown.expect(MessageException.class); - thrown.expectMessage("You must define the following mandatory properties for 'com.foo.project': sonar.sources"); - loadProjectDefinition("simple-project-with-missing-source-dir"); - } - @Test public void shouldNotFailIfBlankSourceDirectory() { loadProjectDefinition("simple-project-with-blank-source-dir");