]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11558 Index basedir by default when sonar.sources is not provided
authorJulien HENRY <julien.henry@sonarsource.com>
Mon, 11 Feb 2019 16:14:32 +0000 (17:14 +0100)
committerSonarTech <sonartech@sonarsource.com>
Mon, 18 Feb 2019 19:20:56 +0000 (20:20 +0100)
server/sonar-docs/src/pages/analysis/analysis-parameters.md
sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputModuleTest.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorBuilder.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorBuilderTest.java

index 600e9055a5d25892c2a5ed87c0b5327ab85b294e..ac7f53c577ddd4a205d7ca64c51449c279888069 100644 (file)
@@ -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 `<groupId>:<artifactId>`
-`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 `<groupId>:<artifactId>`
 
 ## Optional Parameters
 
 ### Project Identity
 Key | Description | Default
 ---|----|---
-`sonar.projectName`|Name of the project that will be displayed on the web interface.|`<name>` 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.|`<name>` 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. | `<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. | `<description>` for Maven projects
-`sonar.links.homepage` | Project home page. Not compatible with Maven. | `<url>` for Maven projects
-`sonar.links.ci` | Continuous integration. Not compatible with Maven. | `<ciManagement><url>` for Maven projects  
-`sonar.links.issue` | Issue tracker. Not compatible with Maven. | `<issueManagement><url>` for Maven projects  
-`sonar.links.scm` | Project source repository. Not compatible with Maven. | `<scm><url>` for Maven projects
-`sonar.links.scm_dev` | Developer connection. Not compatible with Maven. | `<scm><developerConnection>` 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. | `<description>` for Maven projects
+`sonar.links.homepage` | Project home page. | `<url>` for Maven projects
+`sonar.links.ci` | Continuous integration. | `<ciManagement><url>` for Maven projects
+`sonar.links.issue` | Issue tracker. | `<issueManagement><url>` for Maven projects
+`sonar.links.scm` | Project source repository. | `<scm><url>` for Maven projects
+`sonar.links.scm_dev` | Developer connection. | `<scm><developerConnection>` 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
index cad32b8d9809fea20ce987b7a96b7308de758a8a..2dbdd8d2fb0b53da785987569eed82908781282b 100644 (file)
@@ -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<String, String> properties = new HashMap<>();
+  private Map<String, String> properties = new LinkedHashMap<>();
   private ProjectDefinition parent = null;
   private List<ProjectDefinition> subProjects = new ArrayList<>();
 
index 06213be6abb52acfc66141d6e4fc2ebba6f889f7..73fa8dd7629cf526914f0fbc1b7c5cef05f679c5 100644 (file)
@@ -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<Path> initSources(ProjectDefinition module, String propertyKey) {
+    if (!module.properties().containsKey(propertyKey)) {
+      return null;
+    }
     List<Path> 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<Path> getSourceDirsOrFiles() {
-    return sourceDirsOrFiles;
+  public Optional<List<Path>> getSourceDirsOrFiles() {
+    return Optional.ofNullable(sourceDirsOrFiles);
   }
 
-  public List<Path> getTestDirsOrFiles() {
-    return testDirsOrFiles;
+  public Optional<List<Path>> getTestDirsOrFiles() {
+    return Optional.ofNullable(testDirsOrFiles);
   }
 }
index 30eaf20f736214c3cbc4a5aa637560611732ceb0..42394d7f81eabf9c1d7e15e8f0690a05d2cd893f 100644 (file)
@@ -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();
index 5f709ee61c7525c3fc8e28f67b228d854ef691a0..6b4b9a7967716ce169b5d8cd723f48796aade49a 100644 (file)
@@ -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
   };
 
   /**
index 85dd31eb3ecf4e21d3c8c60154959fbb7f75f4e2..2a60b91322a44bbf936bcee9113f0c289449924d 100644 (file)
@@ -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<Path> 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<Path> paths) {
index a70e2ac23890b7db3b9e6aae327d13073f6cf4af..dee1c8b17818a45d6fa5f717a27b23adeded0317 100644 (file)
@@ -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();
+  }
 }
index c9bd41df8e7b259c790396eb54f39b3a38b906a3..5e4099793aa8c2e4a7767146323126fc4431d608 100644 (file)
@@ -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");