]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8631 Only publish input files used by sensors
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Mon, 23 Jan 2017 10:22:39 +0000 (11:22 +0100)
committerDuarte Meneses <duarte.meneses@sonarsource.com>
Fri, 27 Jan 2017 15:26:30 +0000 (16:26 +0100)
86 files changed:
it/it-tests/src/test/java/it/analysis/MultiLanguageTest.java
sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java
sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbstractFilePredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultIndexedFile.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputComponentTree.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputFilePredicate.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OptimizedFilePredicateAdapter.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TestInputFileBuilder.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java
sonar-scanner-engine/foo/src/ManyStatements.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchComponents.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/DeprecatedSensorContext.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/perspectives/ScannerPerspectives.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/test/TestPlanBuilder.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/index/DefaultIndex.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ModuleIssues.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractPhaseExecutor.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/IssuesPhaseExecutor.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PublishPhaseExecutor.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ComponentsPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MeasuresPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RuleFinderCompatibility.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultComponentTree.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultInputModuleHierarchy.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguageVerifier.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java [new file with mode: 0644]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicates.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilder.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilderProvider.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java [new file with mode: 0644]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetection.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactory.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGenerator.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/SameInputFilePredicate.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java [new file with mode: 0644]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmSensor.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/source/LinesSensor.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/deprecated/JavaCpdBlockIndexerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/index/DefaultIndexTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/branch/BranchMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/coverage/GenericCoverageMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/cpd/CpdMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/scm/ScmMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/profiling/PhasesSumUpTimeProfilerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultComponentTreeTest.java [new file with mode: 0644]
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java [new file with mode: 0644]
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/LanguageVerifierTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java [new file with mode: 0644]
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicatesTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileBuilderTest.java [new file with mode: 0644]
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactoryTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorProviderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/report/JSONReportTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
sonar-scanner-protocol/src/main/java/org/sonar/scanner/protocol/output/FileStructure.java

index c9b1b6ff92971de9cb403aa49de95bc81ac77d9f..8ff7baf610287189890e926cf1ebc1c6d91f4234 100644 (file)
@@ -61,7 +61,8 @@ public class MultiLanguageTest {
     SonarScanner build = SonarScanner.create().setProjectDir(ItUtils.projectDir("analysis/xoo-multi-languages"));
     BuildResult result = orchestrator.executeBuild(build);
 
-    assertThat(result.getLogs()).contains("2 files indexed");
+    // 4 files: 1 .xoo, 1.xoo2, 2 .measures
+    assertThat(result.getLogs()).contains("4 files indexed");
     assertThat(result.getLogs()).contains("Quality profile for xoo: one-issue-per-line");
     assertThat(result.getLogs()).contains("Quality profile for xoo2: one-issue-per-line-xoo2");
 
index 302d15ac4d04c626a89d9a09f65c31f9451e96e1..0c5788180fd073fea206a2b4a260b38cce316d4d 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.core.component;
 import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.batch.fs.InputPath;
-import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
 import org.sonar.api.resources.Scopes;
 
index c62cdb26c6067149894b4aad2d77503328fc42cf..b4eb78e67210c646da18d3eb69738dbb247f24a6 100644 (file)
@@ -488,7 +488,9 @@ public interface CoreProperties {
 
   /**
    * @since 5.1
+   * @deprecated since 6.3. No longer taken into consideration as all files are always imported.
    */
+  @Deprecated
   String IMPORT_UNKNOWN_FILES_KEY = "sonar.import_unknown_files";
 
   /**
index 045b2fd5319ed5ea7a4865a3a0311b5c05954cea..4007b74d145df2b00ba66ec31cc7626bb592c9c8 100644 (file)
@@ -29,6 +29,6 @@ public interface FilePredicate {
   /**
    * Test if provided file is valid for this predicate
    */
-  boolean apply(IndexedFile inputFile);
+  boolean apply(InputFile inputFile);
 
 }
index b6e549d28ada27142aeafbd5700e4c8433194b8f..2e5362c194330c0ee63ac62d6331db5c8a7a926e 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.api.batch.fs.internal;
 
 import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.IndexedFile;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.scan.filesystem.PathResolver;
 import org.sonar.api.utils.PathUtils;
@@ -44,7 +43,7 @@ class AbsolutePathPredicate extends AbstractFilePredicate {
   }
 
   @Override
-  public boolean apply(IndexedFile f) {
+  public boolean apply(InputFile f) {
     return path.equals(f.absolutePath());
   }
 
index 2aff265bcf1b3ccd0dfac35d11e7f81ccc4ca118..f58a5a2f5e1eeb8d5317ca8fdf11b0cf79ed3e9e 100644 (file)
 package org.sonar.api.batch.fs.internal;
 
 import com.google.common.collect.Iterables;
-import org.sonar.api.batch.fs.FilePredicate;
 import org.sonar.api.batch.fs.FileSystem.Index;
 import org.sonar.api.batch.fs.InputFile;
 
 /**
- * Partial implementation of {@link FilePredicate}.
+ * Partial implementation of {@link OptimizedFilePredicate}.
  * @since 5.1
  */
 public abstract class AbstractFilePredicate implements OptimizedFilePredicate {
index e000fd1a1b67f6013090a8c9635221fadb36048a..e7afc7600a33797c0e8d4147d8119066aedcb821 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.api.batch.fs.internal;
 import com.google.common.annotations.VisibleForTesting;
 import org.sonar.api.batch.fs.FilePredicate;
 import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.IndexedFile;
 import org.sonar.api.batch.fs.InputFile;
 
 import java.util.ArrayList;
@@ -61,7 +60,7 @@ class AndPredicate extends AbstractFilePredicate {
   }
 
   @Override
-  public boolean apply(IndexedFile f) {
+  public boolean apply(InputFile f) {
     for (OptimizedFilePredicate predicate : predicates) {
       if (!predicate.apply(f)) {
         return false;
index c58d668515b9bb94a9a33623918554e29941e53b..7c7632df8d808574114b5445601725081d8c8dde 100644 (file)
@@ -32,6 +32,7 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.function.Predicate;
 import java.util.stream.StreamSupport;
 
 import javax.annotation.Nullable;
@@ -55,7 +56,7 @@ public class DefaultFileSystem implements FileSystem {
   private Path workDir;
   private Charset encoding;
   protected final FilePredicates predicates;
-  private InputFilePredicate defaultPredicate;
+  private Predicate<InputFile> defaultPredicate;
 
   /**
    * Only for testing
@@ -110,7 +111,7 @@ public class DefaultFileSystem implements FileSystem {
     return this;
   }
 
-  public DefaultFileSystem setDefaultPredicate(@Nullable InputFilePredicate predicate) {
+  public DefaultFileSystem setDefaultPredicate(@Nullable Predicate<InputFile> predicate) {
     this.defaultPredicate = predicate;
     return this;
   }
@@ -161,7 +162,7 @@ public class DefaultFileSystem implements FileSystem {
     Iterable<InputFile> iterable = OptimizedFilePredicateAdapter.create(predicate).get(cache);
     if (defaultPredicate != null) {
       return StreamSupport.stream(iterable.spliterator(), false)
-        .filter(defaultPredicate::apply)::iterator;
+        .filter(defaultPredicate::test)::iterator;
     }
     return iterable;
   }
@@ -279,6 +280,7 @@ public class DefaultFileSystem implements FileSystem {
       return dirMap.get(relativePath);
     }
 
+    @Override
     public InputModule module() {
       return module;
     }
index 642b6e1176b0897d03f4fe90df479e71b3e6ebc1..d29b42c8b591577be19b643f33314b36a630bb19 100644 (file)
@@ -36,8 +36,11 @@ public class DefaultIndexedFile extends DefaultInputComponent implements Indexed
   private String language;
   private final Type type;
 
+  /**
+   * Testing purposes only!
+   */
   public DefaultIndexedFile(String moduleKey, Path moduleBaseDir, String relativePath) {
-    this(moduleKey, moduleBaseDir, relativePath, TestInputFileBuilder.batchId++);
+    this(moduleKey, moduleBaseDir, relativePath, TestInputFileBuilder.nextBatchId());
   }
 
   public DefaultIndexedFile(String moduleKey, Path moduleBaseDir, String relativePath, int batchId) {
index b845be0865ba2bf233e4dd0218465e7fe6f4c48a..36444b4ecb8135c65e595e0c4812d44722cbe260 100644 (file)
@@ -35,7 +35,7 @@ public class DefaultInputDir extends DefaultInputComponent implements InputDir {
   private Path moduleBaseDir;
 
   public DefaultInputDir(String moduleKey, String relativePath) {
-    this(moduleKey, relativePath, TestInputFileBuilder.batchId++);
+    this(moduleKey, relativePath, TestInputFileBuilder.nextBatchId());
   }
 
   public DefaultInputDir(String moduleKey, String relativePath, int batchId) {
index a2c97b8c9549f5730ec61606e8a28ae423e7a50d..cecc2e410d73b8328c38302a70fce6b874f9e0eb 100644 (file)
@@ -24,7 +24,7 @@ import java.io.File;
 import java.nio.charset.Charset;
 import java.nio.file.Path;
 import java.util.Arrays;
-import java.util.function.Function;
+import java.util.function.Consumer;
 
 import javax.annotation.CheckForNull;
 import org.sonar.api.batch.fs.InputFile;
@@ -36,12 +36,13 @@ import org.sonar.api.batch.fs.TextRange;
  */
 public class DefaultInputFile extends DefaultInputComponent implements InputFile {
   private final DefaultIndexedFile indexedFile;
-  private final Function<DefaultInputFile, Metadata> metadataGenerator;
+  private final Consumer<DefaultInputFile> metadataGenerator;
   private Status status;
   private Charset charset;
   private Metadata metadata;
+  private boolean publish = false;
 
-  public DefaultInputFile(DefaultIndexedFile indexedFile, Function<DefaultInputFile, Metadata> metadataGenerator) {
+  public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer<DefaultInputFile> metadataGenerator) {
     super(indexedFile.batchId());
     this.indexedFile = indexedFile;
     this.metadataGenerator = metadataGenerator;
@@ -50,10 +51,18 @@ public class DefaultInputFile extends DefaultInputComponent implements InputFile
 
   private void checkMetadata() {
     if (metadata == null) {
-      setMetadata(metadataGenerator.apply(this));
+      metadataGenerator.accept(this);
     }
   }
 
+  public void setPublish(boolean publish) {
+    this.publish = publish;
+  }
+
+  public boolean publish() {
+    return publish;
+  }
+
   @Override
   public String relativePath() {
     return indexedFile.relativePath();
@@ -253,7 +262,7 @@ public class DefaultInputFile extends DefaultInputComponent implements InputFile
     return Math.abs(Arrays.binarySearch(originalLineOffsets(), globalOffset) + 1);
   }
 
-  private DefaultInputFile setMetadata(Metadata metadata) {
+  public DefaultInputFile setMetadata(Metadata metadata) {
     this.metadata = metadata;
     return this;
   }
index 54f315b342704d53bf49f12f4a6261a8225d3fb6..368f4f9156668fdb214ecb66e39c6f36aa911453 100644 (file)
@@ -30,8 +30,11 @@ public class DefaultInputModule extends DefaultInputComponent implements InputMo
   private final String moduleKey;
   private final ProjectDefinition definition;
 
+  /**
+   * For testing only!
+   */
   public DefaultInputModule(String moduleKey) {
-    this(ProjectDefinition.create().setKey(moduleKey), TestInputFileBuilder.batchId++);
+    this(ProjectDefinition.create().setKey(moduleKey), TestInputFileBuilder.nextBatchId());
   }
 
   public DefaultInputModule(ProjectDefinition definition, int batchId) {
index 1acaf7b2df301e1ef294f50a9d8846e27dada0d6..3fac4b9e6ef4c858cc31042da03bce08cb8894d4 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.api.batch.fs.internal;
 
 import org.sonar.api.batch.fs.FilePredicate;
 import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.IndexedFile;
 import org.sonar.api.batch.fs.InputFile;
 
 import java.util.Collections;
@@ -31,7 +30,7 @@ class FalsePredicate extends AbstractFilePredicate {
   static final FilePredicate FALSE = new FalsePredicate();
 
   @Override
-  public boolean apply(IndexedFile inputFile) {
+  public boolean apply(InputFile inputFile) {
     return false;
   }
 
index 782a379ef7265f8f6b17611dae431f8a9f7aee7d..f083f151063caa41824ac3194db5b1d63944ee27 100644 (file)
@@ -24,7 +24,7 @@ import java.util.Collection;
 import org.sonar.api.batch.fs.InputComponent;
 
 public interface InputComponentTree {
-  public Collection<InputComponent> getChildren(InputComponent module);
+  Collection<InputComponent> getChildren(InputComponent module);
 
-  public InputComponent getParent(InputComponent module);
+  InputComponent getParent(InputComponent module);
 }
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputFilePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputFilePredicate.java
deleted file mode 100644 (file)
index eacd05b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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  02110-1301, USA.
- */
-package org.sonar.api.batch.fs.internal;
-
-import org.sonar.api.batch.fs.InputFile;
-
-@FunctionalInterface
-public interface InputFilePredicate {
-  boolean apply(InputFile inputFile);
-}
index 52930c6e2b6bdd18b53585933b40290849b986ca..b7f7c78fd4c0fcf3820b1f4e15bb39abe230a10e 100644 (file)
@@ -19,7 +19,7 @@
  */
 package org.sonar.api.batch.fs.internal;
 
-import org.sonar.api.batch.fs.IndexedFile;
+import org.sonar.api.batch.fs.InputFile;
 
 /**
  * @since 4.2
@@ -32,7 +32,7 @@ class LanguagePredicate extends AbstractFilePredicate {
   }
 
   @Override
-  public boolean apply(IndexedFile f) {
+  public boolean apply(InputFile f) {
     return language.equals(f.language());
   }
 }
index d51f79d2e13557abb5d11aeec0d819be696f69e0..2a179713f9b6e40979c0a18e4c2cdb97ffc7870a 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.api.batch.fs.internal;
 
 import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.IndexedFile;
+import org.sonar.api.batch.fs.InputFile;
 
 /**
  * @since 4.2
@@ -34,7 +34,7 @@ class NotPredicate extends AbstractFilePredicate {
   }
 
   @Override
-  public boolean apply(IndexedFile f) {
+  public boolean apply(InputFile f) {
     return !predicate.apply(f);
   }
 
index 35fa0a183f350a22c92a4dbe43c8c02df743e3ce..636ac426067b217c0643f6dd94e511ec4132deda 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.api.batch.fs.internal;
 
 import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.IndexedFile;
+import org.sonar.api.batch.fs.InputFile;
 
 class OptimizedFilePredicateAdapter extends AbstractFilePredicate {
 
@@ -31,7 +31,7 @@ class OptimizedFilePredicateAdapter extends AbstractFilePredicate {
   }
 
   @Override
-  public boolean apply(IndexedFile inputFile) {
+  public boolean apply(InputFile inputFile) {
     return unoptimizedPredicate.apply(inputFile);
   }
 
index e539d05a83d991a8e944971eba11e46a89d5db69..644c33b822436dc56d92f46cf92695dce9713b10 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.api.batch.fs.internal;
 
 import com.google.common.annotations.VisibleForTesting;
 import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.IndexedFile;
+import org.sonar.api.batch.fs.InputFile;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -56,7 +56,7 @@ class OrPredicate extends AbstractFilePredicate {
   }
 
   @Override
-  public boolean apply(IndexedFile f) {
+  public boolean apply(InputFile f) {
     for (FilePredicate predicate : predicates) {
       if (predicate.apply(f)) {
         return true;
index 299fb6c9821953bc3cbe3771b9f1c9cbcef03ce4..86cd285f74c5b11cdcbf02b9f2dd8c946c28d343 100644 (file)
@@ -19,7 +19,7 @@
  */
 package org.sonar.api.batch.fs.internal;
 
-import org.sonar.api.batch.fs.IndexedFile;
+import org.sonar.api.batch.fs.InputFile;
 
 /**
  * @since 4.2
@@ -33,7 +33,7 @@ class PathPatternPredicate extends AbstractFilePredicate {
   }
 
   @Override
-  public boolean apply(IndexedFile f) {
+  public boolean apply(InputFile f) {
     return pattern.match(f);
   }
 
index f7e727f45b5d433b51799cc42403e6edac722a01..155a8b6a3ab58d98c7de300f0decada3efb55006 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.api.batch.fs.internal;
 
 import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.IndexedFile;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.utils.PathUtils;
 
@@ -43,7 +42,7 @@ public class RelativePathPredicate extends AbstractFilePredicate {
   }
 
   @Override
-  public boolean apply(IndexedFile f) {
+  public boolean apply(InputFile f) {
     return path.equals(f.relativePath());
   }
 
index 5da964844211c22bc5c4d81f770bd1b45d3cdb01..95890adeab0f6c4f3b9ef5055bd73d1fc5e97fd4 100644 (file)
@@ -29,7 +29,7 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.utils.PathUtils;
 
 public class TestInputFileBuilder {
-  public static int batchId = 1;
+  private static int batchId = 1;
 
   private final int id;
   private final String relativePath;
@@ -44,6 +44,7 @@ public class TestInputFileBuilder {
   private String hash;
   private int nonBlankLines;
   private int[] originalLineOffsets;
+  private boolean publish = true;
 
   public TestInputFileBuilder(String moduleKey, String relativePath) {
     this(moduleKey, relativePath, batchId++);
@@ -56,6 +57,10 @@ public class TestInputFileBuilder {
     this.id = id;
   }
 
+  public static int nextBatchId() {
+    return batchId++;
+  }
+
   public TestInputFileBuilder setModuleBaseDir(Path moduleBaseDir) {
     this.moduleBaseDir = moduleBaseDir.normalize();
     return this;
@@ -106,6 +111,11 @@ public class TestInputFileBuilder {
     return this;
   }
 
+  public TestInputFileBuilder setPublish(boolean publish) {
+    this.publish = publish;
+    return this;
+  }
+
   public TestInputFileBuilder setMetadata(Metadata metadata) {
     this.setLines(metadata.lines());
     this.setLastValidOffset(metadata.lastValidOffset());
@@ -122,9 +132,10 @@ public class TestInputFileBuilder {
   public DefaultInputFile build() {
     DefaultIndexedFile indexedFile = new DefaultIndexedFile(moduleKey, moduleBaseDir, relativePath, type, id);
     indexedFile.setLanguage(language);
-    DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> new Metadata(lines, nonBlankLines, hash, originalLineOffsets, lastValidOffset));
+    DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(new Metadata(lines, nonBlankLines, hash, originalLineOffsets, lastValidOffset)));
     inputFile.setStatus(status);
     inputFile.setCharset(charset);
+    inputFile.setPublish(publish);
     return inputFile;
   }
 }
index c7a58946749685380a52e0c1899892fbfccc2439..c8ca4d9163bb31ba188e54ddae4bd4559aab0c86 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.api.batch.fs.internal;
 
 import org.sonar.api.batch.fs.FilePredicate;
 import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.IndexedFile;
 import org.sonar.api.batch.fs.InputFile;
 
 class TruePredicate extends AbstractFilePredicate {
@@ -29,7 +28,7 @@ class TruePredicate extends AbstractFilePredicate {
   static final FilePredicate TRUE = new TruePredicate();
 
   @Override
-  public boolean apply(IndexedFile inputFile) {
+  public boolean apply(InputFile inputFile) {
     return true;
   }
 
index c3d9fbf0bc1f4d94c6a0f7d4e7512a8e1bc855a2..36fefb2fd295ac703a1239111d44cd5f99759968 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.api.batch.fs.internal;
 
-import org.sonar.api.batch.fs.IndexedFile;
 import org.sonar.api.batch.fs.InputFile;
 
 /**
@@ -34,7 +33,7 @@ class TypePredicate extends AbstractFilePredicate {
   }
 
   @Override
-  public boolean apply(IndexedFile f) {
+  public boolean apply(InputFile f) {
     return type == f.type();
   }
 
index e06847c27e3de456927f1a13dec13c42ff8657d0..b1befd9e62b52fd2273c6ce333b3951393256d35 100644 (file)
@@ -25,7 +25,6 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.FilePredicate;
 import org.sonar.api.batch.fs.FilePredicates;
-import org.sonar.api.batch.fs.IndexedFile;
 import org.sonar.api.batch.fs.InputFile;
 
 import java.io.File;
@@ -48,14 +47,16 @@ public class DefaultFilePredicatesTest {
     moduleBasePath = temp.newFolder().toPath();
   }
 
-  IndexedFile javaFile;
+  InputFile javaFile;
   FilePredicates predicates;
 
   @Before
   public void before() throws IOException {
     predicates = new DefaultFilePredicates(temp.newFolder().toPath());
-    javaFile = new DefaultIndexedFile("foo", moduleBasePath, "src/main/java/struts/Action.java")
-      .setLanguage("java");
+    javaFile = new TestInputFileBuilder("foo", "src/main/java/struts/Action.java")
+      .setModuleBaseDir(moduleBasePath)
+      .setLanguage("java")
+      .build();
   }
 
   @Test
index e581552aa7680e88f3d1021f3561d5302d5ff030..94e8a469cfd0fd14a78b0b48f49cd6c9ad4d2267 100644 (file)
@@ -52,7 +52,7 @@ public class DefaultInputFileTest {
 
     Metadata metadata = new Metadata(42, 42, "", new int[0], 0);
     DefaultIndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/Foo.php", InputFile.Type.TEST, 0).setLanguage("php");
-    DefaultInputFile inputFile = new DefaultInputFile(indexedFile, (f) -> metadata)
+    DefaultInputFile inputFile = new DefaultInputFile(indexedFile, (f) -> f.setMetadata(metadata))
       .setStatus(InputFile.Status.ADDED)
       .setCharset(StandardCharsets.ISO_8859_1);
 
@@ -76,7 +76,7 @@ public class DefaultInputFileTest {
     Metadata metadata = new Metadata(42, 30, "", new int[0], 0);
 
     DefaultInputFile inputFile = new DefaultInputFile(new DefaultIndexedFile("ABCDE", baseDir, "src/Foo.php", InputFile.Type.TEST, 0)
-      .setLanguage("php"), f -> metadata)
+      .setLanguage("php"), f -> f.setMetadata(metadata))
         .setStatus(InputFile.Status.ADDED)
         .setCharset(StandardCharsets.ISO_8859_1);
 
@@ -113,7 +113,7 @@ public class DefaultInputFileTest {
   @Test
   public void checkValidPointer() {
     Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, 15);
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), (f) -> metadata);
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata));
     assertThat(file.newPointer(1, 0).line()).isEqualTo(1);
     assertThat(file.newPointer(1, 0).lineOffset()).isEqualTo(0);
     // Don't fail
@@ -150,7 +150,7 @@ public class DefaultInputFileTest {
   @Test
   public void checkValidPointerUsingGlobalOffset() {
     Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, 15);
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), (f) -> metadata);
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata));
     assertThat(file.newPointer(0).line()).isEqualTo(1);
     assertThat(file.newPointer(0).lineOffset()).isEqualTo(0);
 
@@ -181,7 +181,7 @@ public class DefaultInputFileTest {
   @Test
   public void checkValidRange() {
     Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde"));
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), (f) -> metadata);
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata));
 
     assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 1)).start().line()).isEqualTo(1);
     // Don't fail
@@ -207,7 +207,7 @@ public class DefaultInputFileTest {
   @Test
   public void selectLine() {
     Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde\n\nabc"));
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), (f) -> metadata);
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata));
 
     assertThat(file.selectLine(1).start().line()).isEqualTo(1);
     assertThat(file.selectLine(1).start().lineOffset()).isEqualTo(0);
@@ -231,7 +231,7 @@ public class DefaultInputFileTest {
   @Test
   public void checkValidRangeUsingGlobalOffset() {
     Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, 15);
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), (f) -> metadata);
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata));
     TextRange newRange = file.newRange(10, 13);
     assertThat(newRange.start().line()).isEqualTo(2);
     assertThat(newRange.start().lineOffset()).isEqualTo(0);
@@ -242,7 +242,7 @@ public class DefaultInputFileTest {
   @Test
   public void testRangeOverlap() {
     Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, 15);
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), (f) -> metadata);
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata));
     // Don't fail
     assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)))).isTrue();
     assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isTrue();
diff --git a/sonar-scanner-engine/foo/src/ManyStatements.java b/sonar-scanner-engine/foo/src/ManyStatements.java
deleted file mode 100644 (file)
index ed22970..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.foo;
-
-public class ManyStatements {
-  
-  void foo() {
-    int A1 = 0; int B = 0; int C = 0; int D = 0; int E = 0; int F = 0; int G = 0; int H = 0; int I = 0; int J = 0; int K = 0;
-    int A2 = 0; int B = 0; int C = 0; int D = 0; int E = 0; int F = 0; int G = 0; int H = 0; int I = 0; int J = 0; int K = 0; 
-    int A1 = 0; int B = 0; int C = 0; int D = 0; int E = 0; int F = 0; int G = 0; int H = 0; int I = 0; int J = 0; int K = 0; 
-  }
-
-}
\ No newline at end of file
index d619a516cac0ebd1794d73dbd3e000639332a492..a10e79eaf3dbd5141e5798f06ec5379e075c119e 100644 (file)
@@ -38,9 +38,8 @@ import org.sonar.scanner.scan.report.JSONReport;
 import org.sonar.scanner.scan.report.RuleNameProvider;
 import org.sonar.scanner.scan.report.SourceProvider;
 import org.sonar.scanner.scm.ScmConfiguration;
-import org.sonar.scanner.scm.ScmSensor;
+import org.sonar.scanner.scm.ScmPublisher;
 import org.sonar.scanner.source.CodeColorizerSensor;
-import org.sonar.scanner.source.LinesSensor;
 import org.sonar.scanner.source.ZeroCoverageSensor;
 import org.sonar.scanner.task.ListTask;
 import org.sonar.scanner.task.ScanTask;
@@ -65,9 +64,8 @@ public class BatchComponents {
     if (!analysisMode.isIssues()) {
       // SCM
       components.add(ScmConfiguration.class);
-      components.add(ScmSensor.class);
+      components.add(ScmPublisher.class);
 
-      components.add(LinesSensor.class);
       components.add(ZeroCoverageSensor.class);
       components.add(CodeColorizerSensor.class);
 
index 1fbeed00db834151db7fa954caea6900861ee9b2..446edb161ef39f556f299b99c6fd23c9262ac4cc 100644 (file)
@@ -255,7 +255,7 @@ public class ScannerExtensionDictionnary {
     }
   }
 
-  private boolean shouldKeep(Class type, Object extension, @Nullable DefaultInputModule module, @Nullable ExtensionMatcher matcher) {
+  private static boolean shouldKeep(Class type, Object extension, @Nullable DefaultInputModule module, @Nullable ExtensionMatcher matcher) {
     boolean keep = (ClassUtils.isAssignable(extension.getClass(), type)
       || (org.sonar.api.batch.Sensor.class.equals(type) && ClassUtils.isAssignable(extension.getClass(), Sensor.class)))
       && (matcher == null || matcher.accept(extension));
index 1908cf638b288a8af7b8604c608e845a61cfa4b8..cfc2d8cf89e24013f6e93d4c639a176c0dfdf019 100644 (file)
@@ -68,11 +68,7 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen
     return index.getMeasure(module.key(), metric);
   }
 
-  private String getEffectiveKey(Resource r) {
-    if (r.getEffectiveKey() != null) {
-      return r.getEffectiveKey();
-    }
-
+  private String getComponentKey(Resource r) {
     if (ResourceUtils.isProject(r) || /* For technical projects */ResourceUtils.isRootProject(r)) {
       return r.getKey();
     } else {
@@ -107,12 +103,12 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen
 
   @Override
   public Resource getResource(Resource resource) {
-    return index.getResource(getEffectiveKey(resource));
+    return index.getResource(getComponentKey(resource));
   }
 
   @Override
   public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) {
-    return index.getMeasures(getEffectiveKey(resource), filter);
+    return index.getMeasures(getComponentKey(resource), filter);
   }
 
   @Override
@@ -124,7 +120,7 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen
   @Override
   public Measure saveMeasure(@Nullable Resource resource, Measure measure) {
     Resource resourceOrProject = resourceOrProject(resource);
-    return index.addMeasure(getEffectiveKey(resourceOrProject), measure);
+    return index.addMeasure(getComponentKey(resourceOrProject), measure);
   }
 
   @Override
index f15ba18ea665f98409b4e9b2d24abdcde21256c2..ad2b65bf93413a7c743422057b9090ac21ca7b0e 100644 (file)
@@ -22,6 +22,8 @@ package org.sonar.scanner.deprecated.perspectives;
 import com.google.common.collect.Maps;
 import java.util.Map;
 import javax.annotation.CheckForNull;
+
+import org.sonar.api.batch.fs.InputComponent;
 import org.sonar.api.batch.fs.InputPath;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.component.Perspective;
@@ -29,18 +31,15 @@ import org.sonar.api.component.ResourcePerspectives;
 import org.sonar.api.resources.Resource;
 import org.sonar.api.resources.ResourceUtils;
 import org.sonar.core.component.ComponentKeys;
-import org.sonar.scanner.index.DefaultIndex;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
 
 public class ScannerPerspectives implements ResourcePerspectives {
 
   private final Map<Class<?>, PerspectiveBuilder<?>> builders = Maps.newHashMap();
-  private final DefaultIndex resourceIndex;
   private final InputComponentStore componentStore;
   private final DefaultInputModule module;
 
-  public ScannerPerspectives(PerspectiveBuilder[] builders, DefaultInputModule module, DefaultIndex resourceIndex, InputComponentStore componentStore) {
-    this.resourceIndex = resourceIndex;
+  public ScannerPerspectives(PerspectiveBuilder[] builders, DefaultInputModule module, InputComponentStore componentStore) {
     this.componentStore = componentStore;
     this.module = module;
 
@@ -52,22 +51,15 @@ public class ScannerPerspectives implements ResourcePerspectives {
   @Override
   @CheckForNull
   public <P extends Perspective> P as(Class<P> perspectiveClass, Resource resource) {
-    Resource indexedResource = resource;
-    if (resource.getEffectiveKey() == null) {
-      indexedResource = resourceIndex.getResource(getEffectiveKey(resource));
-    }
-    if (indexedResource != null) {
+    InputComponent component = componentStore.getByKey(getComponentKey(resource));
+    if (component != null) {
       PerspectiveBuilder<P> builder = builderFor(perspectiveClass);
-      return builder.loadPerspective(perspectiveClass, componentStore.getByKey(indexedResource.getEffectiveKey()));
+      return builder.loadPerspective(perspectiveClass, component);
     }
     return null;
   }
 
-  private String getEffectiveKey(Resource r) {
-    if (r.getEffectiveKey() != null) {
-      return r.getEffectiveKey();
-    }
-
+  private String getComponentKey(Resource r) {
     if (ResourceUtils.isProject(r) || /* For technical projects */ResourceUtils.isRootProject(r)) {
       return r.getKey();
     } else {
index 580b0b109443e9fde369d6186f099af1c0b2de26..5f80f14d6b84aa9f614bf8c3199b672a75fcd402 100644 (file)
@@ -25,6 +25,7 @@ import javax.annotation.CheckForNull;
 import org.sonar.api.batch.fs.InputComponent;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputFile.Type;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.test.MutableTestPlan;
 import org.sonar.scanner.deprecated.perspectives.PerspectiveBuilder;
 
@@ -40,8 +41,9 @@ public class TestPlanBuilder extends PerspectiveBuilder<MutableTestPlan> {
   @Override
   public MutableTestPlan loadPerspective(Class<MutableTestPlan> perspectiveClass, InputComponent component) {
     if (component.isFile()) {
-      InputFile inputFile = (InputFile) component;
+      DefaultInputFile inputFile = (DefaultInputFile) component;
       if (inputFile.type() == Type.TEST) {
+        inputFile.setPublish(true);
         if (!testPlanByFile.containsKey(inputFile)) {
           testPlanByFile.put(inputFile, new DefaultTestPlan());
         }
index 48ba1cbf2ab47986198245455594f98c5b889bd0..32019e1f0bdbc5279e64d4697412b24bc18e472d 100644 (file)
@@ -188,7 +188,6 @@ public class DefaultIndex {
       throw new IllegalArgumentException("Unknow input path type: " + inputComponent);
     }
 
-    r.setEffectiveKey(inputComponent.key());
     return r;
   }
 
index e618b1ddb9688385369ea067550553077358ca51..e819b27c52543284979118388c677cb310f640d3 100644 (file)
@@ -95,26 +95,28 @@ public class ModuleIssues {
     return false;
   }
 
-  private void applyFlows(ScannerReport.Issue.Builder builder, ScannerReport.IssueLocation.Builder locationBuilder, ScannerReport.TextRange.Builder textRangeBuilder, Issue issue) {
+  private static void applyFlows(ScannerReport.Issue.Builder builder, ScannerReport.IssueLocation.Builder locationBuilder,
+    ScannerReport.TextRange.Builder textRangeBuilder, Issue issue) {
     ScannerReport.Flow.Builder flowBuilder = ScannerReport.Flow.newBuilder();
     for (Flow flow : issue.flows()) {
-      if (!flow.locations().isEmpty()) {
-        flowBuilder.clear();
-        for (org.sonar.api.batch.sensor.issue.IssueLocation location : flow.locations()) {
-          locationBuilder.clear();
-          locationBuilder.setComponentRef(((DefaultInputComponent) location.inputComponent()).batchId());
-          String message = location.message();
-          if (message != null) {
-            locationBuilder.setMsg(message);
-          }
-          TextRange textRange = location.textRange();
-          if (textRange != null) {
-            locationBuilder.setTextRange(toProtobufTextRange(textRangeBuilder, textRange));
-          }
-          flowBuilder.addLocation(locationBuilder.build());
+      if (flow.locations().isEmpty()) {
+        return;
+      }
+      flowBuilder.clear();
+      for (org.sonar.api.batch.sensor.issue.IssueLocation location : flow.locations()) {
+        locationBuilder.clear();
+        locationBuilder.setComponentRef(((DefaultInputComponent) location.inputComponent()).batchId());
+        String message = location.message();
+        if (message != null) {
+          locationBuilder.setMsg(message);
+        }
+        TextRange textRange = location.textRange();
+        if (textRange != null) {
+          locationBuilder.setTextRange(toProtobufTextRange(textRangeBuilder, textRange));
         }
-        builder.addFlow(flowBuilder.build());
+        flowBuilder.addLocation(locationBuilder.build());
       }
+      builder.addFlow(flowBuilder.build());
     }
   }
 
index ede6ae406fc78752c6211bc039a1409d1a04d221..7316507aed4b5998552ec74f5e9601aa1cc97b59 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.scanner.phases;
 
+
 import org.sonar.api.batch.SensorContext;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.events.BatchStepEvent;
@@ -72,6 +73,8 @@ public abstract class AbstractPhaseExecutor {
     initIssueExclusions();
 
     sensorsExecutor.execute(sensorContext);
+    
+    afterSensors();
 
     if (module.definition().getParent() == null) {
       executeOnRoot();
@@ -81,6 +84,9 @@ public abstract class AbstractPhaseExecutor {
     eventBus.fireEvent(new ProjectAnalysisEvent(module, false));
   }
 
+  protected void afterSensors() {
+  }
+
   protected abstract void executeOnRoot();
 
   private void initIssueExclusions() {
@@ -107,7 +113,7 @@ public abstract class AbstractPhaseExecutor {
   private void cleanMemory() {
     String cleanMemory = "Clean memory";
     eventBus.fireEvent(new BatchStepEvent(cleanMemory, true));
-    //index.clear();
+    // index.clear();
     eventBus.fireEvent(new BatchStepEvent(cleanMemory, false));
   }
 }
index c68bf066b49f114dbdfed89e49cbecfe00d04e1d..478b29bc5d6e0b3b96813497ec03f193610e5a4c 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.scanner.rule.QProfileVerifier;
 import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem;
 import org.sonar.scanner.scan.filesystem.FileSystemLogger;
 import org.sonar.scanner.scan.report.IssuesReports;
+import org.sonar.scanner.scm.ScmPublisher;
 
 public final class IssuesPhaseExecutor extends AbstractPhaseExecutor {
 
index c0d769ac318ef3bf2fb09199c41469f43847f37b..045f1135d738a4f1a85b9b00ff767b65b68882de 100644 (file)
@@ -28,20 +28,23 @@ import org.sonar.scanner.report.ReportPublisher;
 import org.sonar.scanner.rule.QProfileVerifier;
 import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem;
 import org.sonar.scanner.scan.filesystem.FileSystemLogger;
+import org.sonar.scanner.scm.ScmPublisher;
 
 public final class PublishPhaseExecutor extends AbstractPhaseExecutor {
 
   private final EventBus eventBus;
   private final ReportPublisher reportPublisher;
   private final CpdExecutor cpdExecutor;
+  private final ScmPublisher scm;
 
   public PublishPhaseExecutor(InitializersExecutor initializersExecutor, PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, SensorContext sensorContext,
     EventBus eventBus, ReportPublisher reportPublisher, FileSystemLogger fsLogger, DefaultModuleFileSystem fs,
-    QProfileVerifier profileVerifier, IssueExclusionsLoader issueExclusionsLoader, CpdExecutor cpdExecutor) {
+    QProfileVerifier profileVerifier, IssueExclusionsLoader issueExclusionsLoader, CpdExecutor cpdExecutor, ScmPublisher scm) {
     super(initializersExecutor, postJobsExecutor, sensorsExecutor, sensorContext, eventBus, fsLogger, fs, profileVerifier, issueExclusionsLoader);
     this.eventBus = eventBus;
     this.reportPublisher = reportPublisher;
     this.cpdExecutor = cpdExecutor;
+    this.scm = scm;
   }
 
   @Override
@@ -50,6 +53,11 @@ public final class PublishPhaseExecutor extends AbstractPhaseExecutor {
     publishReportJob();
   }
 
+  @Override
+  protected void afterSensors() {
+    scm.publish();
+  }
+
   private void computeDuplications() {
     String stepName = "Computing duplications";
     eventBus.fireEvent(new BatchStepEvent(stepName, true));
index 1449657f23fd85e50d63d3ab432ab344e6026218..d51d3a4b1a4d54343e56d4800491146efd61afaa 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.scanner.report;
 
+import java.util.Collection;
+
 import javax.annotation.CheckForNull;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.CoreProperties;
@@ -29,13 +31,18 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputModule;
 import org.sonar.api.batch.fs.InputPath;
 import org.sonar.api.batch.fs.internal.DefaultInputComponent;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.InputComponentTree;
 import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
+import org.sonar.core.util.CloseableIterator;
+import org.sonar.core.util.stream.Collectors;
 import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.scanner.protocol.output.ScannerReportReader;
 import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
 import org.sonar.scanner.protocol.output.ScannerReport.ComponentLink;
 import org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType;
+import org.sonar.scanner.protocol.output.ScannerReport.Issue;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 
 /**
@@ -45,6 +52,8 @@ public class ComponentsPublisher implements ReportPublisherStep {
 
   private InputComponentTree componentTree;
   private InputModuleHierarchy moduleHierarchy;
+  private ScannerReportReader reader;
+  private ScannerReportWriter writer;
 
   public ComponentsPublisher(InputModuleHierarchy moduleHierarchy, InputComponentTree inputComponentTree) {
     this.moduleHierarchy = moduleHierarchy;
@@ -53,10 +62,24 @@ public class ComponentsPublisher implements ReportPublisherStep {
 
   @Override
   public void publish(ScannerReportWriter writer) {
-    recursiveWriteComponent((DefaultInputComponent) moduleHierarchy.root(), writer);
+    this.reader = new ScannerReportReader(writer.getFileStructure().root());
+    this.writer = writer;
+    recursiveWriteComponent((DefaultInputComponent) moduleHierarchy.root());
   }
 
-  private void recursiveWriteComponent(DefaultInputComponent component, ScannerReportWriter writer) {
+  /**
+   * Writes the tree of components recursively, deep-first. 
+   * @return true if component was written (not skipped)
+   */
+  private boolean recursiveWriteComponent(DefaultInputComponent component) {
+    Collection<InputComponent> children = componentTree.getChildren(component).stream()
+      .filter(c -> recursiveWriteComponent((DefaultInputComponent) c))
+      .collect(Collectors.toList());
+
+    if (shouldSkipComponent(component, children)) {
+      return false;
+    }
+
     ScannerReport.Component.Builder builder = ScannerReport.Component.newBuilder();
 
     // non-null fields
@@ -83,7 +106,7 @@ public class ComponentsPublisher implements ReportPublisherStep {
     }
 
     if (component.isFile()) {
-      InputFile file = (InputFile) component;
+      DefaultInputFile file = (DefaultInputFile) component;
       builder.setIsTest(file.type() == InputFile.Type.TEST);
       builder.setLines(file.lines());
 
@@ -98,18 +121,31 @@ public class ComponentsPublisher implements ReportPublisherStep {
       builder.setPath(path);
     }
 
-    for (InputComponent child : componentTree.getChildren(component)) {
+    for (InputComponent child : children) {
       builder.addChildRef(((DefaultInputComponent) child).batchId());
     }
     writeLinks(component, builder);
     writer.writeComponent(builder.build());
+    return true;
+  }
 
-    for (InputComponent child : componentTree.getChildren(component)) {
-      recursiveWriteComponent((DefaultInputComponent) child, writer);
+  private boolean shouldSkipComponent(DefaultInputComponent component, Collection<InputComponent> children) {
+    if (component instanceof InputDir && children.isEmpty()) {
+      try (CloseableIterator<Issue> componentIssuesIt = reader.readComponentIssues(component.batchId())) {
+        if (!componentIssuesIt.hasNext()) {
+          // no file to publish on a directory without issues -> skip it
+          return true;
+        }
+      }
+    } else if (component instanceof DefaultInputFile) {
+      // skip files not marked for publishing
+      DefaultInputFile inputFile = (DefaultInputFile) component;
+      return !inputFile.publish();
     }
+    return false;
   }
 
-  private void writeVersion(DefaultInputModule module, ScannerReport.Component.Builder builder) {
+  private static void writeVersion(DefaultInputModule module, ScannerReport.Component.Builder builder) {
     ProjectDefinition def = module.definition();
     String version = getVersion(def);
     if (version != null) {
@@ -142,7 +178,7 @@ public class ComponentsPublisher implements ReportPublisherStep {
     return def.getParent() != null ? getVersion(def.getParent()) : null;
   }
 
-  private void writeLinks(InputComponent c, ScannerReport.Component.Builder builder) {
+  private static void writeLinks(InputComponent c, ScannerReport.Component.Builder builder) {
     if (c instanceof InputModule) {
       DefaultInputModule inputModule = (DefaultInputModule) c;
       ProjectDefinition def = inputModule.definition();
index 30e649716d358da2d76caa1c600702a661e53eab..ed54d5261cb8b8751f10f86339a69e6e33f095be 100644 (file)
@@ -104,7 +104,7 @@ public class MeasuresPublisher implements ReportPublisherStep {
     }
   }
 
-  private static void setValueAccordingToType(ScannerReport.Measure.Builder builder, DefaultMeasure measure) {
+  private static void setValueAccordingToType(ScannerReport.Measure.Builder builder, DefaultMeasure<?> measure) {
     Serializable value = measure.value();
     Metric<?> metric = measure.metric();
     if (Boolean.class.equals(metric.valueType())) {
index 4d16945fc9721e3f25c549baab4cab179eba9975..ea78959f3c7d0a249165043bec784d3a28ff50ca 100644 (file)
@@ -33,8 +33,6 @@ import org.sonar.api.rules.RuleFinder;
 import org.sonar.api.rules.RuleQuery;
 import org.sonar.core.util.stream.Collectors;
 
-import static org.sonar.core.util.stream.Collectors.toList;
-
 public class RuleFinderCompatibility implements RuleFinder {
 
   private final Rules rules;
index bf5218f3714e5b90f10bcbd5b724b7d2650d7015..3329036fdaea8c8ab246ff8935eaf25ee0141844 100644 (file)
@@ -27,14 +27,19 @@ import java.util.Map;
 import java.util.Set;
 
 import javax.annotation.CheckForNull;
+
 import org.sonar.api.batch.fs.InputComponent;
 import org.sonar.api.batch.fs.internal.InputComponentTree;
 
+import com.google.common.base.Preconditions;
+
 public class DefaultComponentTree implements InputComponentTree {
   private Map<InputComponent, InputComponent> parents = new HashMap<>();
   private Map<InputComponent, Set<InputComponent>> children = new HashMap<>();
 
   public void index(InputComponent component, InputComponent parent) {
+    Preconditions.checkNotNull(component);
+    Preconditions.checkNotNull(parent);
     parents.put(component, parent);
     Set<InputComponent> list = children.get(parent);
     if (list == null) {
index f1f35acf1f9578a4141d0dbb98e635b4fdaba949..ef036c0bfabd9c0f92a8579111446efd13413ca9 100644 (file)
@@ -26,53 +26,31 @@ import java.util.Map;
 
 import javax.annotation.CheckForNull;
 
-import org.sonar.api.Startable;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.fs.InputModule;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
 import org.sonar.api.scan.filesystem.PathResolver;
-import org.sonar.scanner.scan.filesystem.BatchIdGenerator;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 
-public class DefaultInputModuleHierarchy implements InputModuleHierarchy, Startable {
+public class DefaultInputModuleHierarchy implements InputModuleHierarchy {
   private final PathResolver pathResolver = new PathResolver();
-  private final ImmutableProjectReactor projectReactor;
-  private final DefaultComponentTree componentTree;
-  private final BatchIdGenerator batchIdGenerator;
-
   private DefaultInputModule root;
-  private Map<DefaultInputModule, DefaultInputModule> parents;
-  private Multimap<DefaultInputModule, DefaultInputModule> children;
-
-  public DefaultInputModuleHierarchy(ImmutableProjectReactor projectReactor, DefaultComponentTree componentTree, BatchIdGenerator batchIdGenerator) {
-    this.projectReactor = projectReactor;
-    this.componentTree = componentTree;
-    this.batchIdGenerator = batchIdGenerator;
-  }
-
-  @Override
-  public void start() {
-    doStart(projectReactor.getRoot());
-  }
+  private final Map<DefaultInputModule, DefaultInputModule> parents = new HashMap<>();
+  private final Multimap<DefaultInputModule, DefaultInputModule> children = HashMultimap.create();
 
-  void doStart(ProjectDefinition rootProjectDefinition) {
-    parents = new HashMap<>();
-    children = HashMultimap.create();
-    root = new DefaultInputModule(rootProjectDefinition, batchIdGenerator.get());
-    createChildren(root);
+  public void setRoot(DefaultInputModule root) {
+    this.root = root;
   }
 
-  private void createChildren(DefaultInputModule parent) {
-    for (ProjectDefinition def : parent.definition().getSubProjects()) {
-      DefaultInputModule child = new DefaultInputModule(def, batchIdGenerator.get());
-      parents.put(child, parent);
-      children.put(parent, child);
-      componentTree.index(child, parent);
-      createChildren(child);
-    }
+  public void index(DefaultInputModule child, DefaultInputModule parent) {
+    Preconditions.checkNotNull(child);
+    Preconditions.checkNotNull(parent);
+    parents.put(child, parent);
+    children.put(parent, child);
   }
 
   @Override
@@ -111,9 +89,4 @@ public class DefaultInputModuleHierarchy implements InputModuleHierarchy, Starta
 
     return pathResolver.relativePath(parentBaseDir, moduleBaseDir);
   }
-
-  @Override
-  public void stop() {
-    // nothing to do
-  }
 }
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguageVerifier.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguageVerifier.java
deleted file mode 100644 (file)
index 55f9f1f..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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  02110-1301, USA.
- */
-package org.sonar.scanner.scan;
-
-import org.apache.commons.lang.StringUtils;
-import org.picocontainer.Startable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.fs.internal.DefaultFileSystem;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.MessageException;
-import org.sonar.scanner.repository.language.Language;
-import org.sonar.scanner.repository.language.LanguagesRepository;
-
-/**
- * Verifies that the property sonar.language is valid
- */
-public class LanguageVerifier implements Startable {
-
-  private static final Logger LOG = LoggerFactory.getLogger(LanguageVerifier.class);
-
-  private final Settings settings;
-  private final LanguagesRepository languages;
-  private final DefaultFileSystem fs;
-
-  public LanguageVerifier(Settings settings, LanguagesRepository languages, DefaultFileSystem fs) {
-    this.settings = settings;
-    this.languages = languages;
-    this.fs = fs;
-  }
-
-  @Override
-  public void start() {
-    String languageKey = settings.getString(CoreProperties.PROJECT_LANGUAGE_PROPERTY);
-    if (StringUtils.isNotBlank(languageKey)) {
-      LOG.info("Language is forced to {}", languageKey);
-      Language language = languages.get(languageKey);
-      if (language == null) {
-        throw MessageException.of("You must install a plugin that supports the language '" + languageKey + "'");
-      }
-
-      // force the registration of the language, even if there are no related source files
-      fs.addLanguages(languageKey);
-    }
-  }
-
-  @Override
-  public void stop() {
-    // nothing to do
-  }
-}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java
new file mode 100644 (file)
index 0000000..24c1557
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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  02110-1301, USA.
+ */
+package org.sonar.scanner.scan;
+
+import org.picocontainer.Startable;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.scanner.scan.filesystem.BatchIdGenerator;
+
+public class ModuleIndexer implements Startable {
+  private final ImmutableProjectReactor projectReactor;
+  private final DefaultComponentTree componentTree;
+  private final DefaultInputModuleHierarchy moduleHierarchy;
+  private final BatchIdGenerator batchIdGenerator;
+
+  public ModuleIndexer(ImmutableProjectReactor projectReactor, DefaultComponentTree componentTree,
+    BatchIdGenerator batchIdGenerator, DefaultInputModuleHierarchy moduleHierarchy) {
+    this.projectReactor = projectReactor;
+    this.componentTree = componentTree;
+    this.moduleHierarchy = moduleHierarchy;
+    this.batchIdGenerator = batchIdGenerator;
+  }
+
+  @Override
+  public void start() {
+    DefaultInputModule root = new DefaultInputModule(projectReactor.getRoot(), batchIdGenerator.get());
+    moduleHierarchy.setRoot(root);
+    createChildren(root);
+  }
+
+  private void createChildren(DefaultInputModule parent) {
+    for (ProjectDefinition def : parent.definition().getSubProjects()) {
+      DefaultInputModule child = new DefaultInputModule(def, batchIdGenerator.get());
+      moduleHierarchy.index(child, parent);
+      componentTree.index(child, parent);
+      createChildren(child);
+    }
+  }
+
+  @Override
+  public void stop() {
+    // nothing to do
+  }
+}
index 35dabd15894230ddeddf5b8afd3da2e3390071ca..9c087e1b1d7e15df559c2785c71d66bab06f6dbe 100644 (file)
@@ -60,9 +60,9 @@ import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem;
 import org.sonar.scanner.scan.filesystem.ExclusionFilters;
 import org.sonar.scanner.scan.filesystem.FileIndexer;
 import org.sonar.scanner.scan.filesystem.FileSystemLogger;
-import org.sonar.scanner.scan.filesystem.IndexedFileBuilderProvider;
+import org.sonar.scanner.scan.filesystem.InputFileBuilder;
+import org.sonar.scanner.scan.filesystem.LanguageDetection;
 import org.sonar.scanner.scan.filesystem.MetadataGeneratorProvider;
-import org.sonar.scanner.scan.filesystem.LanguageDetectionFactory;
 import org.sonar.scanner.scan.filesystem.ModuleFileSystemInitializer;
 import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore;
 import org.sonar.scanner.scan.filesystem.StatusDetectionFactory;
@@ -95,10 +95,6 @@ public class ModuleScanContainer extends ComponentContainer {
       module,
       ModuleSettings.class);
 
-    // hack to initialize settings before ExtensionProviders
-    ModuleSettings moduleSettings = getComponentByType(ModuleSettings.class);
-   //module.setSettings(moduleSettings);
-
     if (getComponentByType(AnalysisMode.class).isIssues()) {
       add(IssuesPhaseExecutor.class,
         IssuesReports.class);
@@ -120,10 +116,9 @@ public class ModuleScanContainer extends ComponentContainer {
       new MetadataGeneratorProvider(),
       FileMetadata.class,
       StatusDetectionFactory.class,
-      LanguageDetectionFactory.class,
+      LanguageDetection.class,
       FileIndexer.class,
-      new IndexedFileBuilderProvider(),
-      LanguageVerifier.class,
+      InputFileBuilder.class,
       FileSystemLogger.class,
       DefaultModuleFileSystem.class,
       ModuleFileSystemInitializer.class,
@@ -175,9 +170,6 @@ public class ModuleScanContainer extends ComponentContainer {
     index.setCurrentProject(getComponentByType(DefaultSensorStorage.class));
 
     getComponentByType(AbstractPhaseExecutor.class).execute(module);
-
-    // Free memory since module settings are no more used
-    //module.setSettings(null);
   }
 
 }
index de4bfe28a36077a6f0944bf0a89b1eb2469253e2..0144b2e7a4b90a68c347120a63fd5b943e278cbe 100644 (file)
@@ -147,6 +147,7 @@ public class ProjectScanContainer extends ComponentContainer {
       new AnalysisTempFolderProvider(),
 
       // file system
+      ModuleIndexer.class,
       InputComponentStore.class,
       PathResolver.class,
       DefaultInputModuleHierarchy.class,
index 713ca7a3d89baef557e1415629c41d5a3cbdedbd..cf2f12713d52ecd97948b81c37525e3d63f247aa 100644 (file)
@@ -19,7 +19,7 @@
  */
 package org.sonar.scanner.scan.filesystem;
 
-import org.sonar.api.batch.fs.IndexedFile;
+import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.internal.AbstractFilePredicate;
 
 /**
@@ -40,7 +40,7 @@ class AdditionalFilePredicates {
     }
 
     @Override
-    public boolean apply(IndexedFile f) {
+    public boolean apply(InputFile f) {
       return key.equals(f.key());
     }
   }
index 4b1d99e355c0a4d33a8db36da20829a3980f8f48..61ef1d38d27d6b30c155ed9b5f4a1703b028b109 100644 (file)
@@ -41,7 +41,6 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.fs.IndexedFile;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
 import org.sonar.api.batch.fs.internal.DefaultInputDir;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
@@ -61,8 +60,7 @@ public class FileIndexer {
   private final InputFileFilter[] filters;
   private final boolean isAggregator;
   private final ExclusionFilters exclusionFilters;
-  private final IndexedFileBuilder indexedFileBuilder;
-  private final MetadataGenerator metadataGenerator;
+  private final InputFileBuilder inputFileBuilder;
   private final DefaultComponentTree componentTree;
   private final DefaultInputModule module;
   private final BatchIdGenerator batchIdGenerator;
@@ -71,21 +69,20 @@ public class FileIndexer {
   private ProgressReport progressReport;
 
   public FileIndexer(BatchIdGenerator batchIdGenerator, InputComponentStore componentStore, DefaultInputModule module, ExclusionFilters exclusionFilters,
-    DefaultComponentTree componentTree, IndexedFileBuilder indexedFileBuilder, MetadataGenerator inputFileBuilder, ProjectDefinition def, InputFileFilter[] filters) {
+    DefaultComponentTree componentTree, InputFileBuilder inputFileBuilder, ProjectDefinition def, InputFileFilter[] filters) {
     this.batchIdGenerator = batchIdGenerator;
     this.componentStore = componentStore;
     this.module = module;
     this.componentTree = componentTree;
-    this.indexedFileBuilder = indexedFileBuilder;
-    this.metadataGenerator = inputFileBuilder;
+    this.inputFileBuilder = inputFileBuilder;
     this.filters = filters;
     this.exclusionFilters = exclusionFilters;
     this.isAggregator = !def.getSubProjects().isEmpty();
   }
 
   public FileIndexer(BatchIdGenerator batchIdGenerator, InputComponentStore componentStore, DefaultInputModule module, ExclusionFilters exclusionFilters,
-    DefaultComponentTree componentTree, IndexedFileBuilder indexedFileBuilder, MetadataGenerator inputFileBuilder, ProjectDefinition def) {
-    this(batchIdGenerator, componentStore, module, exclusionFilters, componentTree, indexedFileBuilder, inputFileBuilder, def, new InputFileFilter[0]);
+    DefaultComponentTree componentTree, InputFileBuilder inputFileBuilder, ProjectDefinition def) {
+    this(batchIdGenerator, componentStore, module, exclusionFilters, componentTree, inputFileBuilder, def, new InputFileFilter[0]);
   }
 
   void index(DefaultModuleFileSystem fileSystem) {
@@ -132,14 +129,13 @@ public class FileIndexer {
   private void indexFile(DefaultModuleFileSystem fileSystem, Progress progress, Path sourceFile, InputFile.Type type) throws IOException {
     // get case of real file without resolving link
     Path realFile = sourceFile.toRealPath(LinkOption.NOFOLLOW_LINKS);
-    DefaultIndexedFile indexedFile = indexedFileBuilder.create(realFile, type, fileSystem.baseDirPath());
-    if (indexedFile != null) {
-      InputFile inputFile = new DefaultInputFile(indexedFile, f -> metadataGenerator.readMetadata(f, fileSystem.encoding()));
-      if (exclusionFilters.accept(indexedFile, type) && accept(inputFile)) {
+    DefaultInputFile inputFile = inputFileBuilder.create(realFile, type, fileSystem.encoding());
+    if (inputFile != null) {
+      if (exclusionFilters.accept(inputFile, type) && accept(inputFile)) {
         fileSystem.add(inputFile);
         indexParentDir(fileSystem, inputFile);
-        progress.markAsIndexed(indexedFile);
-        LOG.debug("'{}' indexed {} with language '{}'", indexedFile.relativePath(), type == Type.TEST ? "as test " : "", indexedFile.language());
+        progress.markAsIndexed(inputFile);
+        LOG.debug("'{}' indexed {} with language '{}'", inputFile.relativePath(), type == Type.TEST ? "as test " : "", inputFile.language());
       } else {
         progress.increaseExcludedByPatternsCount();
       }
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilder.java
deleted file mode 100644 (file)
index 1db56df..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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  02110-1301, USA.
- */
-package org.sonar.scanner.scan.filesystem;
-
-import java.nio.file.Path;
-
-import javax.annotation.CheckForNull;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
-import org.sonar.api.config.Settings;
-import org.sonar.api.scan.filesystem.PathResolver;
-
-public class IndexedFileBuilder {
-  private static final Logger LOG = LoggerFactory.getLogger(IndexedFileBuilder.class);
-  private final String moduleKey;
-  private final PathResolver pathResolver;
-  private final LanguageDetection langDetection;
-  private final Settings settings;
-  private final BatchIdGenerator idGenerator;
-
-  IndexedFileBuilder(String moduleKey, PathResolver pathResolver, Settings settings, LanguageDetection langDetection, BatchIdGenerator idGenerator) {
-    this.moduleKey = moduleKey;
-    this.pathResolver = pathResolver;
-    this.settings = settings;
-    this.langDetection = langDetection;
-    this.idGenerator = idGenerator;
-  }
-
-  @CheckForNull
-  DefaultIndexedFile create(Path file, InputFile.Type type, Path moduleBaseDir) {
-    String relativePath = pathResolver.relativePath(moduleBaseDir, file);
-    if (relativePath == null) {
-      LOG.warn("File '{}' is ignored. It is not located in module basedir '{}'.", file.toAbsolutePath(), moduleBaseDir);
-      return null;
-    }
-    DefaultIndexedFile indexedFile = new DefaultIndexedFile(moduleKey, moduleBaseDir, relativePath, type, idGenerator.get());
-    String language = langDetection.language(indexedFile);
-    if (language == null && !settings.getBoolean(CoreProperties.IMPORT_UNKNOWN_FILES_KEY)) {
-      LOG.debug("'{}' language is not supported by any analyzer. Skipping it.", relativePath);
-      return null;
-    }
-
-    indexedFile.setLanguage(language);
-    return indexedFile;
-  }
-}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilderProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilderProvider.java
deleted file mode 100644 (file)
index e0bbf85..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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  02110-1301, USA.
- */
-package org.sonar.scanner.scan.filesystem;
-
-import org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.config.Settings;
-import org.sonar.api.scan.filesystem.PathResolver;
-
-public class IndexedFileBuilderProvider extends ProviderAdapter {
-
-  public IndexedFileBuilder provide(ProjectDefinition def, PathResolver pathResolver, Settings settings,
-    LanguageDetectionFactory langDetectionFactory, BatchIdGenerator idGenerator) {
-    return new IndexedFileBuilder(def.getKey(), pathResolver, settings, langDetectionFactory.create(), idGenerator);
-  }
-
-}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java
new file mode 100644 (file)
index 0000000..c382696
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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  02110-1301, USA.
+ */
+package org.sonar.scanner.scan.filesystem;
+
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+
+import javax.annotation.CheckForNull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.scan.filesystem.PathResolver;
+
+public class InputFileBuilder {
+  private static final Logger LOG = LoggerFactory.getLogger(InputFileBuilder.class);
+  private final String moduleKey;
+  private final Path moduleBaseDir;
+  private final PathResolver pathResolver;
+  private final LanguageDetection langDetection;
+  private final BatchIdGenerator idGenerator;
+  private final MetadataGenerator metadataGenerator;
+
+  public InputFileBuilder(DefaultInputModule module, PathResolver pathResolver, LanguageDetection langDetection, MetadataGenerator metadataGenerator,
+    BatchIdGenerator idGenerator) {
+    this.moduleKey = module.key();
+    this.moduleBaseDir = module.definition().getBaseDir().toPath();
+    this.pathResolver = pathResolver;
+    this.langDetection = langDetection;
+    this.metadataGenerator = metadataGenerator;
+    this.idGenerator = idGenerator;
+  }
+
+  @CheckForNull
+  DefaultInputFile create(Path file, InputFile.Type type, Charset defaultEncoding) {
+    String relativePath = pathResolver.relativePath(moduleBaseDir, file);
+    if (relativePath == null) {
+      LOG.warn("File '{}' is ignored. It is not located in module basedir '{}'.", file.toAbsolutePath(), moduleBaseDir);
+      return null;
+    }
+    DefaultIndexedFile indexedFile = new DefaultIndexedFile(moduleKey, moduleBaseDir, relativePath, type, idGenerator.get());
+    String language = langDetection.language(indexedFile);
+    if (language == null && langDetection.forcedLanguage() != null) {
+      LOG.warn("File '{}' is ignored because it doens't belong to the forced langauge '{}'", file.toAbsolutePath(), langDetection.forcedLanguage());
+      return null;
+    }
+    indexedFile.setLanguage(language);
+    return new DefaultInputFile(indexedFile, f -> metadataGenerator.setMetadata(f, defaultEncoding));
+  }
+}
index b83402a77332d497588d1c10cd07d8c6718916cd..847f3f2f3640a95333807f833ffeb8a9f7a08bbf 100644 (file)
@@ -30,6 +30,7 @@ import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.ScannerSide;
 import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
 import org.sonar.api.batch.fs.internal.PathPattern;
 import org.sonar.api.config.Settings;
@@ -40,7 +41,8 @@ import org.sonar.scanner.repository.language.LanguagesRepository;
 /**
  * Detect language of a source file based on its suffix and configured patterns.
  */
-class LanguageDetection {
+@ScannerSide
+public class LanguageDetection {
 
   private static final Logger LOG = LoggerFactory.getLogger(LanguageDetection.class);
 
@@ -51,7 +53,7 @@ class LanguageDetection {
   private final List<String> languagesToConsider = Lists.newArrayList();
   private final String forcedLanguage;
 
-  LanguageDetection(Settings settings, LanguagesRepository languages) {
+  public LanguageDetection(Settings settings, LanguagesRepository languages) {
     for (Language language : languages.all()) {
       String[] filePatterns = settings.getStringArray(getFileLangPatternPropKey(language.key()));
       PathPattern[] pathPatterns = PathPattern.create(filePatterns);
@@ -75,14 +77,19 @@ class LanguageDetection {
     // First try with lang patterns
     if (forcedLanguage != null) {
       if (!patternsByLanguage.containsKey(forcedLanguage)) {
-        throw MessageException.of("No language is installed with key '" + forcedLanguage + "'. Please update property '" + CoreProperties.PROJECT_LANGUAGE_PROPERTY + "'");
+        throw MessageException.of("You must install a plugin that supports the language '" + forcedLanguage + "'");
       }
+      LOG.info("Language is forced to {}", forcedLanguage);
       languagesToConsider.add(forcedLanguage);
     } else {
       languagesToConsider.addAll(patternsByLanguage.keySet());
     }
   }
 
+  public String forcedLanguage() {
+    return forcedLanguage;
+  }
+
   Map<String, PathPattern[]> patternsByLanguage() {
     return patternsByLanguage;
   }
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactory.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactory.java
deleted file mode 100644 (file)
index 91e389d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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  02110-1301, USA.
- */
-package org.sonar.scanner.scan.filesystem;
-
-import org.sonar.api.batch.ScannerSide;
-import org.sonar.api.config.Settings;
-import org.sonar.scanner.repository.language.LanguagesRepository;
-
-@ScannerSide
-public class LanguageDetectionFactory {
-  private final Settings settings;
-  private final LanguagesRepository languages;
-
-  public LanguageDetectionFactory(Settings settings, LanguagesRepository languages) {
-    this.settings = settings;
-    this.languages = languages;
-  }
-
-  public LanguageDetection create() {
-    return new LanguageDetection(settings, languages);
-  }
-}
index 5468bd7ae6ebf8535c9d5dd1ff713ff1dede166c..ace650416747bd22b50f4503e7907230749c3c73 100644 (file)
@@ -31,6 +31,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.fs.InputFile.Type;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.FileMetadata;
 import org.sonar.api.batch.fs.internal.Metadata;
 
@@ -44,8 +45,10 @@ class MetadataGenerator {
 
   private final StatusDetection statusDetection;
   private final FileMetadata fileMetadata;
+  private final DefaultInputModule inputModule;
 
-  MetadataGenerator(StatusDetection statusDetection, FileMetadata fileMetadata) {
+  MetadataGenerator(DefaultInputModule inputModule, StatusDetection statusDetection, FileMetadata fileMetadata) {
+    this.inputModule = inputModule;
     this.statusDetection = statusDetection;
     this.fileMetadata = fileMetadata;
   }
@@ -76,15 +79,15 @@ class MetadataGenerator {
     }
   }
 
-  public Metadata readMetadata(final DefaultInputFile inputFile, Charset defaultEncoding) {
+  public void setMetadata(final DefaultInputFile inputFile, Charset defaultEncoding) {
     try {
       Charset charset = detectCharset(inputFile.file(), defaultEncoding);
       inputFile.setCharset(charset);
       Metadata metadata = fileMetadata.readMetadata(inputFile.file(), charset);
-      inputFile.setStatus(statusDetection.status(inputFile.moduleKey(), inputFile.relativePath(), metadata.hash()));
+      inputFile.setMetadata(metadata);
+      inputFile.setStatus(statusDetection.status(inputModule.definition().getKeyWithBranch(), inputFile.relativePath(), metadata.hash()));
       LOG.debug("'{}' generated metadata {} with and charset '{}'",
         inputFile.relativePath(), inputFile.type() == Type.TEST ? "as test " : "", charset);
-      return metadata;
     } catch (Exception e) {
       throw new IllegalStateException(e);
     }
index 13bfd484184790de8ee0284a96899dc6c6c1b154..216fe5df2bbb0414c7788aa5b63f4b56b23caace 100644 (file)
@@ -21,11 +21,12 @@ package org.sonar.scanner.scan.filesystem;
 
 import org.picocontainer.injectors.ProviderAdapter;
 import org.sonar.api.batch.ScannerSide;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.FileMetadata;
 
 @ScannerSide
 public class MetadataGeneratorProvider extends ProviderAdapter {
-  public MetadataGenerator provide(StatusDetectionFactory statusDetectionFactory, FileMetadata fileMetadata) {
-    return new MetadataGenerator(statusDetectionFactory.create(), fileMetadata);
+  public MetadataGenerator provide(DefaultInputModule inputModule, StatusDetectionFactory statusDetectionFactory, FileMetadata fileMetadata) {
+    return new MetadataGenerator(inputModule, statusDetectionFactory.create(), fileMetadata);
   }
 }
index 5ec413082cd745bcd5bb0677a9d4f03711a62ba6..83faa5e4cc06ade76f3dcdc7c7c3c3f9bc90ba22 100644 (file)
  */
 package org.sonar.scanner.scan.filesystem;
 
+import java.util.function.Predicate;
+
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.InputFilePredicate;
 import org.sonar.scanner.repository.FileData;
 import org.sonar.scanner.repository.ProjectRepositories;
 
-public class SameInputFilePredicate implements InputFilePredicate {
+public class SameInputFilePredicate implements Predicate<InputFile> {
   private static final Logger LOG = LoggerFactory.getLogger(SameInputFilePredicate.class);
   private final ProjectRepositories projectRepositories;
   private final String moduleKey;
@@ -39,7 +40,7 @@ public class SameInputFilePredicate implements InputFilePredicate {
   }
 
   @Override
-  public boolean apply(InputFile inputFile) {
+  public boolean test(InputFile inputFile) {
     FileData fileDataPerPath = projectRepositories.fileData(moduleKey, inputFile.relativePath());
     if (fileDataPerPath == null) {
       // ADDED
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java
new file mode 100644 (file)
index 0000000..8c8f8ff
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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  02110-1301, USA.
+ */
+package org.sonar.scanner.scm;
+
+import java.io.File;
+import java.util.LinkedList;
+import java.util.List;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.InstantiationStrategy;
+import org.sonar.api.batch.ScannerSide;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputFile.Status;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.scanner.protocol.output.ScannerReportWriter;
+import org.sonar.scanner.protocol.output.ScannerReport.Changesets.Builder;
+import org.sonar.scanner.repository.FileData;
+import org.sonar.scanner.repository.ProjectRepositories;
+import org.sonar.scanner.scan.ImmutableProjectReactor;
+import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem;
+import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore;
+
+@InstantiationStrategy(InstantiationStrategy.PER_PROJECT)
+@ScannerSide
+public final class ScmPublisher {
+
+  private static final Logger LOG = Loggers.get(ScmPublisher.class);
+
+  private final DefaultInputModule inputModule;
+  private final ScmConfiguration configuration;
+  private final ProjectRepositories projectRepositories;
+  private final ModuleInputComponentStore componentStore;
+
+  private DefaultModuleFileSystem fs;
+  private ScannerReportWriter writer;
+
+  public ScmPublisher(DefaultInputModule inputModule, ScmConfiguration configuration, ProjectRepositories projectRepositories,
+    ModuleInputComponentStore componentStore, DefaultModuleFileSystem fs, ImmutableProjectReactor reactor) {
+    this.inputModule = inputModule;
+    this.configuration = configuration;
+    this.projectRepositories = projectRepositories;
+    this.componentStore = componentStore;
+    this.fs = fs;
+    File reportDir = new File(reactor.getRoot().getWorkDir(), "batch-report");
+    writer = new ScannerReportWriter(reportDir);
+  }
+
+  public void publish() {
+    if (configuration.isDisabled()) {
+      LOG.info("SCM Publisher is disabled");
+      return;
+    }
+    if (configuration.provider() == null) {
+      LOG.info("No SCM system was detected. You can use the '" + CoreProperties.SCM_PROVIDER_KEY + "' property to explicitly specify it.");
+      return;
+    }
+
+    List<InputFile> filesToBlame = collectFilesToBlame(writer);
+    if (!filesToBlame.isEmpty()) {
+      String key = configuration.provider().key();
+      LOG.info("SCM provider for this project is: " + key);
+      DefaultBlameOutput output = new DefaultBlameOutput(writer, filesToBlame);
+      try {
+        configuration.provider().blameCommand().blame(new DefaultBlameInput(fs, filesToBlame), output);
+      } catch (Exception e) {
+        output.finish(false);
+        throw e;
+      }
+      output.finish(true);
+    }
+  }
+
+  private List<InputFile> collectFilesToBlame(ScannerReportWriter writer) {
+    if (configuration.forceReloadAll()) {
+      LOG.warn("Forced reloading of SCM data for all files.");
+    }
+    List<InputFile> filesToBlame = new LinkedList<>();
+    for (InputFile f : componentStore.inputFiles()) {
+      DefaultInputFile inputFile = (DefaultInputFile) f;
+      if (!inputFile.publish()) {
+        continue;
+      }
+      if (configuration.forceReloadAll() || f.status() != Status.SAME) {
+        addIfNotEmpty(filesToBlame, f);
+      } else {
+        // File status is SAME so that mean fileData exists
+        FileData fileData = projectRepositories.fileData(inputModule.definition().getKeyWithBranch(), f.relativePath());
+        if (StringUtils.isEmpty(fileData.revision())) {
+          addIfNotEmpty(filesToBlame, f);
+        } else {
+          askToCopyDataFromPreviousAnalysis((DefaultInputFile) f, writer);
+        }
+      }
+    }
+    return filesToBlame;
+  }
+
+  private void askToCopyDataFromPreviousAnalysis(DefaultInputFile f, ScannerReportWriter writer) {
+    Builder scmBuilder = ScannerReport.Changesets.newBuilder();
+    scmBuilder.setComponentRef(f.batchId());
+    scmBuilder.setCopyFromPrevious(true);
+    writer.writeComponentChangesets(scmBuilder.build());
+  }
+
+  private static void addIfNotEmpty(List<InputFile> filesToBlame, InputFile f) {
+    if (!f.isEmpty()) {
+      filesToBlame.add(f);
+    }
+  }
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmSensor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmSensor.java
deleted file mode 100644 (file)
index 3f00b5b..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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  02110-1301, USA.
- */
-package org.sonar.scanner.scm;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputFile.Status;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.scanner.protocol.output.ScannerReport;
-import org.sonar.scanner.protocol.output.ScannerReport.Changesets.Builder;
-import org.sonar.scanner.report.ReportPublisher;
-import org.sonar.scanner.repository.FileData;
-import org.sonar.scanner.repository.ProjectRepositories;
-
-public final class ScmSensor implements Sensor {
-
-  private static final Logger LOG = Loggers.get(ScmSensor.class);
-
-  private final ProjectDefinition projectDefinition;
-  private final ScmConfiguration configuration;
-  private final FileSystem fs;
-  private final ProjectRepositories projectRepositories;
-  private final ReportPublisher publishReportJob;
-
-  public ScmSensor(ProjectDefinition projectDefinition, ScmConfiguration configuration,
-    ProjectRepositories projectRepositories, FileSystem fs, ReportPublisher publishReportJob) {
-    this.projectDefinition = projectDefinition;
-    this.configuration = configuration;
-    this.projectRepositories = projectRepositories;
-    this.fs = fs;
-    this.publishReportJob = publishReportJob;
-  }
-
-  @Override
-  public void describe(SensorDescriptor descriptor) {
-    descriptor.name("SCM Sensor");
-  }
-
-  @Override
-  public void execute(SensorContext context) {
-    if (configuration.isDisabled()) {
-      LOG.info("SCM Publisher is disabled");
-      return;
-    }
-    if (configuration.provider() == null) {
-      LOG.info("No SCM system was detected. You can use the '" + CoreProperties.SCM_PROVIDER_KEY + "' property to explicitly specify it.");
-      return;
-    }
-
-    List<InputFile> filesToBlame = collectFilesToBlame();
-    if (!filesToBlame.isEmpty()) {
-      String key = configuration.provider().key();
-      LOG.info("SCM provider for this project is: " + key);
-      DefaultBlameOutput output = new DefaultBlameOutput(publishReportJob.getWriter(), filesToBlame);
-      try {
-        configuration.provider().blameCommand().blame(new DefaultBlameInput(fs, filesToBlame), output);
-      } catch (Exception e) {
-        output.finish(false);
-        throw e;
-      }
-      output.finish(true);
-    }
-  }
-
-  private List<InputFile> collectFilesToBlame() {
-    if (configuration.forceReloadAll()) {
-      LOG.warn("Forced reloading of SCM data for all files.");
-    }
-    List<InputFile> filesToBlame = new LinkedList<>();
-    for (InputFile f : fs.inputFiles(fs.predicates().all())) {
-      if (configuration.forceReloadAll() || f.status() != Status.SAME) {
-        addIfNotEmpty(filesToBlame, f);
-      } else {
-        // File status is SAME so that mean fileData exists
-        FileData fileData = projectRepositories.fileData(projectDefinition.getKeyWithBranch(), f.relativePath());
-        if (StringUtils.isEmpty(fileData.revision())) {
-          addIfNotEmpty(filesToBlame, f);
-        } else {
-          askToCopyDataFromPreviousAnalysis((DefaultInputFile) f);
-        }
-      }
-    }
-    return filesToBlame;
-  }
-
-  private void askToCopyDataFromPreviousAnalysis(DefaultInputFile f) {
-    Builder scmBuilder = ScannerReport.Changesets.newBuilder();
-    scmBuilder.setComponentRef(f.batchId());
-    scmBuilder.setCopyFromPrevious(true);
-    publishReportJob.getWriter().writeComponentChangesets(scmBuilder.build());
-  }
-
-  private static void addIfNotEmpty(List<InputFile> filesToBlame, InputFile f) {
-    if (!f.isEmpty()) {
-      filesToBlame.add(f);
-    }
-  }
-
-}
index 8600ec3fdab2c56e25b325e6e7d55de932bf6a9b..61b5c31ab3cc33a736f4beccd55e85ff16ecdaae 100644 (file)
@@ -25,6 +25,7 @@ import org.sonar.api.batch.AnalysisMode;
 import org.sonar.api.batch.fs.FileSystem;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.rule.ActiveRules;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.coverage.NewCoverage;
@@ -160,6 +161,7 @@ public class DefaultSensorContext implements SensorContext {
 
   @Override
   public void markForPublishing(InputFile inputFile) {
-    
+    DefaultInputFile file = (DefaultInputFile) inputFile;
+    file.setPublish(true);
   }
 }
index 051565781cd6c1f6d5598d62464373cc6e1f2d15..3ba1565e874f08e1b44fe1233f7b684f256ba78c 100644 (file)
@@ -204,6 +204,9 @@ public class DefaultSensorStorage implements SensorStorage {
 
   @Override
   public void store(Measure newMeasure) {
+    if (newMeasure.inputComponent() instanceof DefaultInputFile) {
+      ((DefaultInputFile) newMeasure.inputComponent()).setPublish(true);
+    }
     saveMeasure(newMeasure.inputComponent(), (DefaultMeasure<?>) newMeasure);
   }
 
@@ -344,6 +347,9 @@ public class DefaultSensorStorage implements SensorStorage {
 
   @Override
   public void store(Issue issue) {
+    if (issue.primaryLocation().inputComponent() instanceof DefaultInputFile) {
+      ((DefaultInputFile) issue.primaryLocation().inputComponent()).setPublish(true);
+    }
     moduleIssues.initAndAddIssue(issue);
   }
 
@@ -351,6 +357,7 @@ public class DefaultSensorStorage implements SensorStorage {
   public void store(DefaultHighlighting highlighting) {
     ScannerReportWriter writer = reportPublisher.getWriter();
     DefaultInputFile inputFile = (DefaultInputFile) highlighting.inputFile();
+    inputFile.setPublish(true);
     int componentRef = inputFile.batchId();
     if (writer.hasComponentData(FileStructure.Domain.SYNTAX_HIGHLIGHTINGS, componentRef)) {
       throw new UnsupportedOperationException("Trying to save highlighting twice for the same file is not supported: " + inputFile.absolutePath());
@@ -375,6 +382,7 @@ public class DefaultSensorStorage implements SensorStorage {
   public void store(DefaultSymbolTable symbolTable) {
     ScannerReportWriter writer = reportPublisher.getWriter();
     DefaultInputFile inputFile = (DefaultInputFile) symbolTable.inputFile();
+    inputFile.setPublish(true);
     int componentRef = inputFile.batchId();
     if (writer.hasComponentData(FileStructure.Domain.SYMBOLS, componentRef)) {
       throw new UnsupportedOperationException("Trying to save symbol table twice for the same file is not supported: " + symbolTable.inputFile().absolutePath());
@@ -405,31 +413,34 @@ public class DefaultSensorStorage implements SensorStorage {
 
   @Override
   public void store(DefaultCoverage defaultCoverage) {
-    if (coverageExclusions.isExcluded(defaultCoverage.inputFile())) {
+    DefaultInputFile inputFile = (DefaultInputFile) defaultCoverage.inputFile();
+    inputFile.setPublish(true);
+    if (coverageExclusions.isExcluded(inputFile)) {
       return;
     }
     if (defaultCoverage.linesToCover() > 0) {
-      saveCoverageMetricInternal(defaultCoverage.inputFile(), LINES_TO_COVER, new DefaultMeasure<Integer>().forMetric(LINES_TO_COVER).withValue(defaultCoverage.linesToCover()));
-      saveCoverageMetricInternal(defaultCoverage.inputFile(), UNCOVERED_LINES,
+      saveCoverageMetricInternal(inputFile, LINES_TO_COVER, new DefaultMeasure<Integer>().forMetric(LINES_TO_COVER).withValue(defaultCoverage.linesToCover()));
+      saveCoverageMetricInternal(inputFile, UNCOVERED_LINES,
         new DefaultMeasure<Integer>().forMetric(UNCOVERED_LINES).withValue(defaultCoverage.linesToCover() - defaultCoverage.coveredLines()));
-      saveCoverageMetricInternal(defaultCoverage.inputFile(), COVERAGE_LINE_HITS_DATA,
+      saveCoverageMetricInternal(inputFile, COVERAGE_LINE_HITS_DATA,
         new DefaultMeasure<String>().forMetric(COVERAGE_LINE_HITS_DATA).withValue(KeyValueFormat.format(defaultCoverage.hitsByLine())));
     }
     if (defaultCoverage.conditions() > 0) {
-      saveCoverageMetricInternal(defaultCoverage.inputFile(), CONDITIONS_TO_COVER,
+      saveCoverageMetricInternal(inputFile, CONDITIONS_TO_COVER,
         new DefaultMeasure<Integer>().forMetric(CONDITIONS_TO_COVER).withValue(defaultCoverage.conditions()));
-      saveCoverageMetricInternal(defaultCoverage.inputFile(), UNCOVERED_CONDITIONS,
+      saveCoverageMetricInternal(inputFile, UNCOVERED_CONDITIONS,
         new DefaultMeasure<Integer>().forMetric(UNCOVERED_CONDITIONS).withValue(defaultCoverage.conditions() - defaultCoverage.coveredConditions()));
-      saveCoverageMetricInternal(defaultCoverage.inputFile(), COVERED_CONDITIONS_BY_LINE,
+      saveCoverageMetricInternal(inputFile, COVERED_CONDITIONS_BY_LINE,
         new DefaultMeasure<String>().forMetric(COVERED_CONDITIONS_BY_LINE).withValue(KeyValueFormat.format(defaultCoverage.coveredConditionsByLine())));
-      saveCoverageMetricInternal(defaultCoverage.inputFile(), CONDITIONS_BY_LINE,
+      saveCoverageMetricInternal(inputFile, CONDITIONS_BY_LINE,
         new DefaultMeasure<String>().forMetric(CONDITIONS_BY_LINE).withValue(KeyValueFormat.format(defaultCoverage.conditionsByLine())));
     }
   }
 
   @Override
   public void store(DefaultCpdTokens defaultCpdTokens) {
-    InputFile inputFile = defaultCpdTokens.inputFile();
+    DefaultInputFile inputFile = (DefaultInputFile) defaultCpdTokens.inputFile();
+    inputFile.setPublish(true);
     PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language()));
     List<Block> blocks = blockChunker.chunk(inputFile.key(), defaultCpdTokens.getTokenLines());
     index.insert(inputFile, blocks);
@@ -446,6 +457,7 @@ public class DefaultSensorStorage implements SensorStorage {
 
   @Override
   public void store(AnalysisError analysisError) {
+    ((DefaultInputFile) analysisError.inputFile()).setPublish(true);
     // no op
   }
 
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/source/LinesSensor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/source/LinesSensor.java
deleted file mode 100644 (file)
index 726eec0..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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  02110-1301, USA.
- */
-package org.sonar.scanner.source;
-
-import org.sonar.api.batch.Phase;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.measures.CoreMetrics;
-
-@Phase(name = Phase.Name.POST)
-public final class LinesSensor implements Sensor {
-
-  @Override
-  public void describe(SensorDescriptor descriptor) {
-    descriptor.name("Lines Sensor");
-  }
-
-  @Override
-  public void execute(final SensorContext context) {
-    FileSystem fs = context.fileSystem();
-    for (InputFile f : fs.inputFiles(fs.predicates().hasType(Type.MAIN))) {
-      ((DefaultMeasure<Integer>) context.<Integer>newMeasure()
-        .on(f)
-        .forMetric(CoreMetrics.LINES)
-        .withValue(f.lines()))
-          .setFromCore()
-          .save();
-      if (f.language() == null) {
-        // As an approximation for files with no language plugin we consider every non blank line as ncloc
-        ((DefaultMeasure<Integer>) context.<Integer>newMeasure()
-          .on(f)
-          .forMetric(CoreMetrics.NCLOC)
-          .withValue(((DefaultInputFile) f).nonBlankLines()))
-            .save();
-        // No test and no coverage on those files
-        ((DefaultMeasure<Integer>) context.<Integer>newMeasure()
-          .on(f)
-          .forMetric(CoreMetrics.LINES_TO_COVER)
-          .withValue(0))
-            .save();
-      }
-    }
-  }
-
-}
index a40589be0f727601ee3809d06ed6f70794338bc5..13c2409c895c5c9983247068c10787f6fb29bfa8 100644 (file)
@@ -69,7 +69,9 @@ public class JavaCpdBlockIndexerTest {
 
     File baseDir = temp.newFolder();
     DefaultFileSystem fs = new DefaultFileSystem(baseDir);
-    file = new TestInputFileBuilder("foo", "src/ManyStatements.java").setLanguage(JAVA).build();
+    file = new TestInputFileBuilder("foo", "src/ManyStatements.java")
+      .setModuleBaseDir(baseDir.toPath())
+      .setLanguage(JAVA).build();
     fs.add(file);
     File ioFile = file.file();
     FileUtils.copyURLToFile(this.getClass().getResource("ManyStatements.java"), ioFile);
index d8cc87b574a687a5b6818decea9ad584bc22328e..2eadd1f51708e173a608bf794cd909ca6953d1cd 100644 (file)
 package org.sonar.scanner.index;
 
 import java.io.IOException;
-import org.apache.commons.io.FileUtils;
+import java.util.Collections;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.fs.InputDir;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputDir;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.InputComponentTree;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilters;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.resources.Directory;
 import org.sonar.api.resources.File;
 import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RuleFinder;
-import org.sonar.scanner.FakeJava;
+import org.sonar.scanner.scan.filesystem.InputComponentStore;
 import org.sonar.scanner.scan.measure.MeasureCache;
 import org.sonar.scanner.sensor.DefaultSensorStorage;
 
@@ -48,97 +54,83 @@ public class DefaultIndexTest {
   @org.junit.Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
-  DefaultIndex index = null;
-  Rule rule;
-  RuleFinder ruleFinder;
-  Project project;
-  Project moduleA;
-  Project moduleB;
-  Project moduleB1;
+  private DefaultIndex index = null;
+  private Rule rule;
+  private RuleFinder ruleFinder;
+  private Project project;
+  private Project moduleA;
+  private Project moduleB;
+  private Project moduleB1;
+  private InputComponentStore componentStore;
+  private InputComponentTree componentTree;
 
   private java.io.File baseDir;
-  // TODO
-/*
- * 
 
   @Before
   public void createIndex() throws IOException {
     ruleFinder = mock(RuleFinder.class);
-
-    DefaultProjectTree projectTree = mock(DefaultProjectTree.class);
-    BatchComponentCache resourceCache = new BatchComponentCache();
-    index = new DefaultIndex(resourceCache, projectTree, mock(MeasureCache.class), mock(MetricFinder.class));
+    componentStore = mock(InputComponentStore.class);
+    componentTree = mock(InputComponentTree.class);
+    index = new DefaultIndex(componentStore, componentTree, mock(MeasureCache.class), mock(MetricFinder.class));
 
     baseDir = temp.newFolder();
-    project = new Project("project");
-    when(projectTree.getProjectDefinition(project)).thenReturn(ProjectDefinition.create().setBaseDir(baseDir));
-    moduleA = new Project("moduleA").setParent(project);
-    when(projectTree.getProjectDefinition(moduleA)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleA")));
-    moduleB = new Project("moduleB").setParent(project);
-    when(projectTree.getProjectDefinition(moduleB)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB")));
-    moduleB1 = new Project("moduleB1").setParent(moduleB);
-    when(projectTree.getProjectDefinition(moduleB1)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB/moduleB1")));
+
+    ProjectDefinition rootDef = ProjectDefinition.create().setKey("project").setBaseDir(baseDir);
+    ProjectDefinition moduleADef = ProjectDefinition.create().setKey("moduleA").setBaseDir(new java.io.File(baseDir, "moduleA"));
+    ProjectDefinition moduleBDef = ProjectDefinition.create().setKey("moduleB").setBaseDir(new java.io.File(baseDir, "moduleB"));
+    ProjectDefinition moduleB1Def = ProjectDefinition.create().setKey("moduleB1").setBaseDir(new java.io.File(baseDir, "moduleB/moduleB1"));
+
+    rootDef.addSubProject(moduleADef);
+    rootDef.addSubProject(moduleBDef);
+    moduleBDef.addSubProject(moduleB1Def);
+
+    project = new Project(rootDef);
+    moduleA = new Project(moduleADef);
+    moduleB = new Project(moduleBDef);
+    moduleB1 = new Project(moduleB1Def);
 
     RulesProfile rulesProfile = RulesProfile.create();
     rule = Rule.create("repoKey", "ruleKey", "Rule");
     rule.setId(1);
     rulesProfile.activateRule(rule, null);
-    index.setCurrentProject(project, mock(DefaultSensorStorage.class));
-    index.doStart(project);
-  }
-
-  @Test
-  public void shouldIndexParentOfDeprecatedFiles() {
-    File file = File.create("src/org/foo/Bar.java", null, false);
-    assertThat(index.index(file)).isTrue();
-
-    Directory reference = Directory.create("src/org/foo");
-    assertThat(index.getResource(reference).getName()).isEqualTo("src/org/foo");
-    assertThat(index.getChildren(reference)).hasSize(1);
-    assertThat(index.getParent(reference)).isInstanceOf(Project.class);
-  }
-
-  @Test
-  public void shouldIndexTreeOfResources() {
-    Directory directory = Directory.create("src/org/foo");
-    File file = File.create("src/org/foo/Bar.java", FakeJava.INSTANCE, false);
-
-    assertThat(index.index(directory)).isTrue();
-    assertThat(index.index(file, directory)).isTrue();
-
-    File fileRef = File.create("src/org/foo/Bar.java", null, false);
-    assertThat(index.getResource(fileRef).getKey()).isEqualTo("src/org/foo/Bar.java");
-    assertThat(index.getResource(fileRef).getLanguage().getKey()).isEqualTo("java");
-    assertThat(index.getChildren(fileRef)).isEmpty();
-    assertThat(index.getParent(fileRef)).isInstanceOf(Directory.class);
+    index.setCurrentProject(mock(DefaultSensorStorage.class));
   }
 
   @Test
-  public void shouldNotIndexResourceIfParentNotIndexed() {
-    Directory directory = Directory.create("src/org/other");
-    File file = File.create("src/org/foo/Bar.java", null, false);
+  public void shouldGetHierarchy() {
+    InputComponent component = new DefaultInputModule("module1");
+    InputFile file1 = new TestInputFileBuilder("module1", "src/org/foo/Bar.java").build();
 
-    assertThat(index.index(file, directory)).isFalse();
+    when(componentStore.getByKey("module1")).thenReturn(component);
+    when(componentStore.getByKey("module1:src/org/foo/Bar.java")).thenReturn(file1);
+    when(componentTree.getParent(file1)).thenReturn(component);
+    when(componentTree.getChildren(component)).thenReturn(Collections.singleton(file1));
 
-    File fileRef = File.create("src/org/foo/Bar.java", null, false);
-    assertThat(index.getChildren(fileRef)).isEmpty();
-    assertThat(index.getParent(fileRef)).isNull();
-  }
-
-  @Test
-  public void shouldNotIndexResourceWhenAddingMeasure() {
-    Resource dir = Directory.create("src/org/foo");
-    index.addMeasure(dir, new Measure("ncloc").setValue(50.0));
+    assertThat(index.getParent("module1:src/org/foo/Bar.java").getKey()).isEqualTo("module1");
+    assertThat(index.getParent("module1")).isNull();
 
-    assertThat(index.getMeasures(dir, MeasuresFilters.metric("ncloc"))).isNull();
+    assertThat(index.getChildren("module1")).containsOnly(File.create("src/org/foo/Bar.java"));
+    assertThat(index.getChildren("module1:src/org/foo/Bar.java")).isEmpty();
   }
 
   @Test
-  public void shouldComputePathOfIndexedModules() {
-    assertThat(index.getResource(project).getPath()).isNull();
-    assertThat(index.getResource(moduleA).getPath()).isEqualTo("moduleA");
-    assertThat(index.getResource(moduleB).getPath()).isEqualTo("moduleB");
-    assertThat(index.getResource(moduleB1).getPath()).isEqualTo("moduleB1");
+  public void shouldTransformToResource() {
+    DefaultInputModule component = new DefaultInputModule(ProjectDefinition.create()
+      .setKey("module1")
+      .setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, "branch1"), 1);
+    InputFile file1 = new TestInputFileBuilder("module1", "src/org/foo/Bar.java").build();
+    InputDir dir = new DefaultInputDir("module1", "src");
+
+    assertThat(index.toResource(component)).isInstanceOf(Project.class);
+    assertThat(index.toResource(component).getKey()).isEqualTo("module1");
+    assertThat(index.toResource(component).getEffectiveKey()).isEqualTo("module1:branch1");
+
+    assertThat(index.toResource(file1)).isInstanceOf(File.class);
+    assertThat(index.toResource(file1).getKey()).isEqualTo("src/org/foo/Bar.java");
+    assertThat(index.toResource(file1).getPath()).isEqualTo("src/org/foo/Bar.java");
+
+    assertThat(index.toResource(dir)).isInstanceOf(Directory.class);
+    assertThat(index.toResource(dir).getKey()).isEqualTo("src");
+    assertThat(index.toResource(dir).getPath()).isEqualTo("src");
   }
- */
 }
index d579e26a77e46dba77cde32decb587e14f40b246..5147e929dc2c17f7aac37f645b61ed4014c562ca 100644 (file)
@@ -36,6 +36,7 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.scanner.mediumtest.TaskResult;
 import org.sonar.xoo.XooPlugin;
+import org.sonar.xoo.rule.XooRulesDefinition;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -49,6 +50,9 @@ public class BranchMediumTest {
 
   public ScannerMediumTester tester = ScannerMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
+    .addRules(new XooRulesDefinition())
+    // active a rule just to be sure that xoo files are published
+    .addActiveRule("xoo", "xoo:OneIssuePerFile", null, "One Issue Per File", null, null, null)
     .addDefaultQProfile("xoo", "Sonar Way")
     .build();
 
index 16a6428dab231d123701edff86575fe3c4fefec2..1cf428dc0ca5a995c9b21a06280bcbac063e811b 100644 (file)
@@ -69,7 +69,6 @@ public class GenericCoverageMediumTest {
 
     assertThat(result.allMeasures().get(noConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value")
       .containsOnly(
-        tuple(CoreMetrics.LINES_KEY, 8, ""),
         tuple(CoreMetrics.LINES_TO_COVER_KEY, 2, ""),
         tuple(CoreMetrics.UNCOVERED_LINES_KEY, 1, ""),
         tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "6=1;7=0"));
@@ -81,7 +80,6 @@ public class GenericCoverageMediumTest {
 
     assertThat(result.allMeasures().get(withConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value")
       .containsOnly(
-        tuple(CoreMetrics.LINES_KEY, 6, ""),
         tuple(CoreMetrics.LINES_TO_COVER_KEY, 1, ""),
         tuple(CoreMetrics.UNCOVERED_LINES_KEY, 0, ""),
         tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "3=1"),
@@ -112,7 +110,6 @@ public class GenericCoverageMediumTest {
 
     assertThat(result.allMeasures().get(noConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value")
       .containsOnly(
-        tuple(CoreMetrics.LINES_KEY, 8, ""),
         tuple(CoreMetrics.LINES_TO_COVER_KEY, 2, ""),
         tuple(CoreMetrics.UNCOVERED_LINES_KEY, 0, ""),
         tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "6=1;7=1"));
@@ -124,7 +121,6 @@ public class GenericCoverageMediumTest {
 
     assertThat(result.allMeasures().get(withConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value")
       .containsOnly(
-        tuple(CoreMetrics.LINES_KEY, 6, ""),
         tuple(CoreMetrics.LINES_TO_COVER_KEY, 1, ""),
         tuple(CoreMetrics.UNCOVERED_LINES_KEY, 0, ""),
         tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "3=2"),
index 49c8056ff3e4778768d188ef4581dcb3745a6c58..6326e015bc6eabde059e056727742728bee47a34 100644 (file)
@@ -42,6 +42,7 @@ import org.sonar.scanner.mediumtest.TaskResult;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.xoo.XooPlugin;
 import org.sonar.xoo.lang.CpdTokenizerSensor;
+import org.sonar.xoo.rule.XooRulesDefinition;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -64,6 +65,9 @@ public class CpdMediumTest {
   public ScannerMediumTester tester = ScannerMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
     .addDefaultQProfile("xoo", "Sonar Way")
+    .addRules(new XooRulesDefinition())
+    // active a rule just to be sure that xoo files are published
+    .addActiveRule("xoo", "xoo:OneIssuePerFile", null, "One Issue Per File", null, null, null)
     .build();
 
   private File baseDir;
index de4ecaac49678d5c0c5c591f2720deb0e324e1da..db4cb6db8deeb36600556c06730d54130df466b3 100644 (file)
@@ -30,7 +30,6 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.scanner.mediumtest.ScannerMediumTester;
@@ -75,63 +74,6 @@ public class MeasuresMediumTest {
     srcDir.mkdir();
   }
 
-  @Test
-  public void computeMeasuresOnTempProject() throws IOException {
-    File xooFile = new File(srcDir, "sample.xoo");
-    File xooMeasureFile = new File(srcDir, "sample.xoo.measures");
-    FileUtils.write(xooFile, "Sample xoo\ncontent");
-    FileUtils.write(xooMeasureFile, "lines:20");
-
-    TaskResult result = tester.newTask()
-      .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.task", "scan")
-        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
-        .put("sonar.projectKey", "com.foo.project")
-        .put("sonar.projectName", "Foo Project")
-        .put("sonar.projectVersion", "1.0-SNAPSHOT")
-        .put("sonar.projectDescription", "Description of Foo Project")
-        .put("sonar.sources", "src")
-        .put("sonar.cpd.xoo.skip", "true")
-        .build())
-      .start();
-
-    Map<String, List<Measure>> allMeasures = result.allMeasures();
-
-    assertThat(allMeasures.get("com.foo.project")).extracting("metricKey", "stringValue.value").isEmpty();
-
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value").containsOnly(
-      tuple(CoreMetrics.LINES_KEY, 2));
-  }
-
-  @Test
-  public void computeLinesOnAllFiles() throws IOException {
-    File xooFile = new File(srcDir, "sample.xoo");
-    FileUtils.write(xooFile, "Sample xoo\n\ncontent");
-
-    File otherFile = new File(srcDir, "sample.other");
-    FileUtils.write(otherFile, "Sample other\ncontent\n");
-
-    TaskResult result = tester.newTask()
-      .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.task", "scan")
-        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
-        .put("sonar.projectKey", "com.foo.project")
-        .put("sonar.projectName", "Foo Project")
-        .put("sonar.projectVersion", "1.0-SNAPSHOT")
-        .put("sonar.projectDescription", "Description of Foo Project")
-        .put("sonar.sources", "src")
-        .put("sonar.import_unknown_files", "true")
-        .build())
-      .start();
-
-    Map<String, List<Measure>> allMeasures = result.allMeasures();
-
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value")
-      .contains(tuple("lines", 3));
-    assertThat(allMeasures.get("com.foo.project:src/sample.other")).extracting("metricKey", "intValue.value")
-      .contains(tuple("lines", 3), tuple("ncloc", 2));
-  }
-
   @Test
   public void applyExclusionsOnCoverageMeasures() throws IOException {
     File xooFile = new File(srcDir, "sample.xoo");
@@ -155,8 +97,7 @@ public class MeasuresMediumTest {
     Map<String, List<Measure>> allMeasures = result.allMeasures();
 
     assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value")
-      .containsOnly(tuple("lines", 3),
-        tuple("lines_to_cover", 2));
+      .containsOnly(tuple("lines_to_cover", 2));
 
     result = tester.newTask()
       .properties(ImmutableMap.<String, String>builder()
@@ -173,7 +114,7 @@ public class MeasuresMediumTest {
 
     allMeasures = result.allMeasures();
     assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value")
-      .containsOnly(tuple("lines", 3));
+      .isEmpty();
   }
 
   @Test
@@ -199,8 +140,7 @@ public class MeasuresMediumTest {
     Map<String, List<Measure>> allMeasures = result.allMeasures();
 
     assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value")
-      .containsOnly(tuple("lines", 3),
-        tuple("lines_to_cover", 2));
+      .containsOnly(tuple("lines_to_cover", 2));
 
     assertThat(logTester.logs(LoggerLevel.WARN))
       .contains("Coverage measure for metric 'lines_to_cover' should not be saved directly by a Sensor. Plugin should be updated to use SensorContext::newCoverage instead.");
@@ -257,7 +197,7 @@ public class MeasuresMediumTest {
     Map<String, List<Measure>> allMeasures = result.allMeasures();
 
     assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value", "stringValue.value")
-      .containsExactly(tuple("lines", 4, ""), tuple("ncloc_data", 0, "1=1;4=1"));
+      .containsExactly(tuple("ncloc_data", 0, "1=1;4=1"));
   }
 
 }
index f0462e6206b21356340efa8d0b39bf18d97c00f4..cd369da5e54319d51b42b84b186a5ecb4e3ad264 100644 (file)
@@ -40,6 +40,7 @@ import org.sonar.scanner.repository.FileData;
 import org.sonar.scanner.protocol.output.ScannerReport.Component;
 import org.sonar.scanner.protocol.output.ScannerReportReader;
 import org.sonar.xoo.XooPlugin;
+import org.sonar.xoo.rule.XooRulesDefinition;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -64,6 +65,9 @@ public class ScmMediumTest {
   public ScannerMediumTester tester = ScannerMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
     .addDefaultQProfile("xoo", "Sonar Way")
+    .addRules(new XooRulesDefinition())
+    // active a rule just to be sure that xoo files are published
+    .addActiveRule("xoo", "xoo:OneIssuePerFile", null, "One Issue Per File", null, null, null)
     .addFileData("com.foo.project", CHANGED_CONTENT_SCM_ON_SERVER_XOO, new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), null))
     .addFileData("com.foo.project", SAME_CONTENT_NO_SCM_ON_SERVER_XOO, new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), null))
     .addFileData("com.foo.project", SAME_CONTENT_SCM_ON_SERVER_XOO, new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), "1.1"))
@@ -82,7 +86,6 @@ public class ScmMediumTest {
 
   @Test
   public void testScmMeasure() throws IOException {
-
     File baseDir = prepareProject();
 
     tester.newTask()
@@ -242,6 +245,8 @@ public class ScmMediumTest {
 
     assertThat(getChangesets(baseDir, NO_BLAME_SCM_ON_SERVER_XOO)).isNull();
 
+    // 5 .xoo files + 3 .scm files, but only 4 marked for publishing. 1 file is SAME so not included in the total
+    assertThat(logTester.logs()).containsSubsequence("8 files indexed");
     assertThat(logTester.logs()).containsSubsequence("4 files to be analyzed", "3/4 files analyzed");
     assertThat(logTester.logs()).containsSubsequence(MISSING_BLAME_INFORMATION_FOR_THE_FOLLOWING_FILES, "  * " + noBlameScmOnServer.getPath().replaceAll("\\\\", "/"));
   }
index 6d7249b1eba690134b05b4a8c44224f654740695..2e69ae0bb7ae4508b0d3e2ecc322e27e2dbf9918 100644 (file)
@@ -29,14 +29,11 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.Decorator;
 import org.sonar.api.batch.Initializer;
 import org.sonar.api.batch.PostJob;
 import org.sonar.api.batch.Sensor;
 import org.sonar.api.batch.SensorContext;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.events.DecoratorExecutionHandler;
-import org.sonar.api.batch.events.DecoratorsPhaseHandler;
 import org.sonar.api.batch.events.InitializerExecutionHandler;
 import org.sonar.api.batch.events.InitializersPhaseHandler;
 import org.sonar.api.batch.events.PostJobExecutionHandler;
@@ -238,26 +235,6 @@ public class PhasesSumUpTimeProfilerTest {
     };
   }
 
-  private DecoratorExecutionHandler.DecoratorExecutionEvent decoratorEvent(final Decorator decorator, final boolean start) {
-    return new DecoratorExecutionHandler.DecoratorExecutionEvent() {
-
-      @Override
-      public boolean isStart() {
-        return start;
-      }
-
-      @Override
-      public boolean isEnd() {
-        return !start;
-      }
-
-      @Override
-      public Decorator getDecorator() {
-        return decorator;
-      }
-    };
-  }
-
   private PostJobExecutionHandler.PostJobExecutionEvent postJobEvent(final PostJob postJob, final boolean start) {
     return new PostJobExecutionHandler.PostJobExecutionEvent() {
 
@@ -338,26 +315,6 @@ public class PhasesSumUpTimeProfilerTest {
     };
   }
 
-  private DecoratorsPhaseHandler.DecoratorsPhaseEvent decoratorsEvent(final boolean start) {
-    return new DecoratorsPhaseHandler.DecoratorsPhaseEvent() {
-
-      @Override
-      public boolean isStart() {
-        return start;
-      }
-
-      @Override
-      public boolean isEnd() {
-        return !start;
-      }
-
-      @Override
-      public List<Decorator> getDecorators() {
-        return null;
-      }
-    };
-  }
-
   private ProjectAnalysisEvent projectEvent(final Project project, final boolean start) {
     return new ProjectAnalysisHandler.ProjectAnalysisEvent() {
       @Override
index 1fbb2ad50b45cdfc8de377d256c5f80434a00b41..0d2b7b7c7d6784fca04248bb913ef657cc6085cd 100644 (file)
@@ -38,6 +38,7 @@ import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.scanner.ProjectAnalysisInfo;
 import org.sonar.scanner.protocol.output.FileStructure;
+import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Component;
 import org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType;
 import org.sonar.scanner.report.ComponentsPublisher;
@@ -65,6 +66,10 @@ public class ComponentsPublisherTest {
     writer = new ScannerReportWriter(outputDir);
   }
 
+  private void writeIssue(int componentId) {
+    writer.writeComponentIssues(componentId, Collections.singleton(ScannerReport.Issue.newBuilder().build()));
+  }
+
   @Test
   public void add_components_to_report() throws Exception {
     ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class);
@@ -96,10 +101,13 @@ public class ComponentsPublisherTest {
     DefaultInputFile file = new TestInputFileBuilder("module1", "src/Foo.java", 4).setLines(2).build();
     tree.index(file, dir);
 
-    DefaultInputFile fileWithoutLang = new TestInputFileBuilder("module1", "src/make", 5).setLines(10).build();
+    DefaultInputFile file2 = new TestInputFileBuilder("module1", "src/Foo2.java", 5).setPublish(false).setLines(2).build();
+    tree.index(file2, dir);
+
+    DefaultInputFile fileWithoutLang = new TestInputFileBuilder("module1", "src/make", 6).setLines(10).build();
     tree.index(fileWithoutLang, dir);
 
-    DefaultInputFile testFile = new TestInputFileBuilder("module1", "test/FooTest.java", 6).setType(Type.TEST).setLines(4).build();
+    DefaultInputFile testFile = new TestInputFileBuilder("module1", "test/FooTest.java", 7).setType(Type.TEST).setLines(4).build();
     tree.index(testFile, dir);
 
     ComponentsPublisher publisher = new ComponentsPublisher(moduleHierarchy, tree);
@@ -109,11 +117,13 @@ public class ComponentsPublisherTest {
     assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 2)).isTrue();
     assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 3)).isTrue();
     assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 4)).isTrue();
-    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 5)).isTrue();
     assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 6)).isTrue();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 7)).isTrue();
 
+    // not marked for publishing
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 5)).isFalse();
     // no such reference
-    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 7)).isFalse();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 8)).isFalse();
 
     ScannerReportReader reader = new ScannerReportReader(outputDir);
     Component rootProtobuf = reader.readComponent(1);
@@ -128,6 +138,59 @@ public class ComponentsPublisherTest {
     assertThat(module1Protobuf.getVersion()).isEqualTo("1.0");
   }
 
+  @Test
+  public void should_skip_dir_without_published_files() {
+    ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class);
+    when(projectAnalysisInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12"));
+
+    ProjectDefinition rootDef = ProjectDefinition.create()
+      .setKey("foo")
+      .setProperty(CoreProperties.PROJECT_VERSION_PROPERTY, "1.0")
+      .setName("Root project")
+      .setDescription("Root description");
+    DefaultInputModule root = new DefaultInputModule(rootDef, 1);
+
+    moduleHierarchy = mock(InputModuleHierarchy.class);
+    when(moduleHierarchy.root()).thenReturn(root);
+    when(moduleHierarchy.children(root)).thenReturn(Collections.emptyList());
+
+    // dir with files
+    DefaultInputDir dir = new DefaultInputDir("module1", "src", 2);
+    tree.index(dir, root);
+
+    // dir without files and issues
+    DefaultInputDir dir2 = new DefaultInputDir("module1", "src2", 3);
+    tree.index(dir2, root);
+
+    // dir without files but has issues
+    DefaultInputDir dir3 = new DefaultInputDir("module1", "src3", 4);
+    tree.index(dir3, root);
+    writeIssue(4);
+
+    DefaultInputFile file = new TestInputFileBuilder("module1", "src/Foo.java", 5).setLines(2).build();
+    tree.index(file, dir);
+
+    DefaultInputFile file2 = new TestInputFileBuilder("module1", "src2/Foo2.java", 6).setPublish(false).setLines(2).build();
+    tree.index(file2, dir2);
+
+    DefaultInputFile file3 = new TestInputFileBuilder("module1", "src2/Foo3.java", 7).setPublish(false).setLines(2).build();
+    tree.index(file3, dir3);
+
+    ComponentsPublisher publisher = new ComponentsPublisher(moduleHierarchy, tree);
+    publisher.publish(writer);
+
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isTrue();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 2)).isTrue();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 5)).isTrue();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 4)).isTrue();
+
+    // file was not marked for publishing and directory doesn't contain issues, so directory won't be included as well
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 3)).isFalse();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 6)).isFalse();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 7)).isFalse();
+
+  }
+
   @Test
   public void add_components_without_version_and_name() throws IOException {
     ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class);
index f6caf2f6bbd7f0b66c8301d2d776c3af056b4141..d9a9cec17a7102f5d283d9d4720e0268557d26ea 100644 (file)
@@ -49,9 +49,6 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 public class MeasuresPublisherTest {
-
-  private static final String FILE_KEY = "foo:src/Foo.php";
-
   @Rule
   public ExpectedException thrown = ExpectedException.none();
 
@@ -65,12 +62,14 @@ public class MeasuresPublisherTest {
   private File outputDir;
   private ScannerReportWriter writer;
   private DefaultInputFile inputFile;
+  private DefaultInputModule InputModule;
 
   @Before
   public void prepare() throws IOException {
-    inputFile = new TestInputFileBuilder("foo", "src/Foo.php").build();
+    InputModule = new DefaultInputModule("foo");
+    inputFile = new TestInputFileBuilder("foo", "src/Foo.php").setPublish(true).build();
     componentCache = new InputComponentStore();
-    componentCache.put(new DefaultInputModule("foo"));
+    componentCache.put(InputModule);
     componentCache.put(inputFile);
     measureCache = mock(MeasureCache.class);
     when(measureCache.byComponentKey(anyString())).thenReturn(Collections.<DefaultMeasure<?>>emptyList());
@@ -86,12 +85,12 @@ public class MeasuresPublisherTest {
     // String value
     DefaultMeasure<String> stringMeasure = new DefaultMeasure<String>().forMetric(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION)
       .withValue("foo bar");
-    when(measureCache.byComponentKey(FILE_KEY)).thenReturn(asList(measure, stringMeasure));
+    when(measureCache.byComponentKey(inputFile.key())).thenReturn(asList(measure, stringMeasure));
 
     publisher.publish(writer);
     ScannerReportReader reader = new ScannerReportReader(outputDir);
 
-    assertThat(reader.readComponentMeasures(1)).hasSize(0);
+    assertThat(reader.readComponentMeasures(InputModule.batchId())).hasSize(0);
     try (CloseableIterator<ScannerReport.Measure> componentMeasures = reader.readComponentMeasures(inputFile.batchId())) {
       assertThat(componentMeasures).hasSize(2);
     }
@@ -100,7 +99,7 @@ public class MeasuresPublisherTest {
   @Test
   public void fail_with_IAE_when_measure_has_no_value() throws Exception {
     DefaultMeasure<Integer> measure = new DefaultMeasure<Integer>().forMetric(CoreMetrics.LINES_TO_COVER);
-    when(measureCache.byComponentKey(FILE_KEY)).thenReturn(Collections.singletonList(measure));
+    when(measureCache.byComponentKey(inputFile.key())).thenReturn(Collections.singletonList(measure));
 
     try {
       publisher.publish(writer);
index 6e5ee36b18245320a435287d4edcabcd2d034ad8..d2aa0ec35bfdc6928bb5157e431dc11ec7a3e68a 100644 (file)
@@ -61,7 +61,7 @@ public class MetadataPublisherTest {
   @Before
   public void prepare() {
     projectDef = ProjectDefinition.create().setKey("foo");
-    rootModule = new DefaultInputModule(projectDef, TestInputFileBuilder.batchId++);
+    rootModule = new DefaultInputModule(projectDef, TestInputFileBuilder.nextBatchId());
     projectAnalysisInfo = mock(ProjectAnalysisInfo.class);
     when(projectAnalysisInfo.analysisDate()).thenReturn(new Date(1234567L));
     inputModuleHierarchy = mock(InputModuleHierarchy.class);
index 8a749037deef989f9c3e0eaee8ee350da5550d7b..0dde3f3f0f696b7adc37b42f7abc03559cc08e37 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.scanner.rule;
 import com.google.common.collect.ImmutableList;
 import java.util.LinkedList;
 import java.util.List;
-import org.apache.commons.lang.mutable.MutableBoolean;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
@@ -36,7 +35,6 @@ import org.sonar.scanner.rule.ModuleQProfiles;
 import org.sonarqube.ws.QualityProfiles.SearchWsResponse.QualityProfile;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultComponentTreeTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultComponentTreeTest.java
new file mode 100644 (file)
index 0000000..b799074
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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  02110-1301, USA.
+ */
+package org.sonar.scanner.scan;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.batch.fs.internal.DefaultInputComponent;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+
+public class DefaultComponentTreeTest {
+  private DefaultComponentTree tree;
+
+  @Before
+  public void setUp() {
+    tree = new DefaultComponentTree();
+  }
+
+  @Test
+  public void test() {
+    DefaultInputComponent root = new DefaultInputModule("root");
+    DefaultInputComponent mod1 = new DefaultInputModule("mod1");
+    DefaultInputComponent mod2 = new DefaultInputModule("mod2");
+    DefaultInputComponent mod3 = new DefaultInputModule("mod3");
+    DefaultInputComponent mod4 = new DefaultInputModule("mod4");
+
+    tree.index(mod1, root);
+    tree.index(mod2, mod1);
+    tree.index(mod3, root);
+    tree.index(mod4, root);
+
+    assertThat(tree.getChildren(root)).containsOnly(mod1, mod3, mod4);
+    assertThat(tree.getChildren(mod4)).isEmpty();
+    assertThat(tree.getChildren(mod1)).containsOnly(mod2);
+
+    assertThat(tree.getParent(mod4)).isEqualTo(root);
+    assertThat(tree.getParent(mod2)).isEqualTo(mod1);
+    assertThat(tree.getParent(mod1)).isEqualTo(root);
+    assertThat(tree.getParent(root)).isNull();
+  }
+}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java
new file mode 100644 (file)
index 0000000..5037a27
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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  02110-1301, USA.
+ */
+package org.sonar.scanner.scan;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+
+public class DefaultInputModuleHierarchyTest {
+  private DefaultInputModuleHierarchy moduleHierarchy;
+
+  @Before
+  public void setUp() {
+    moduleHierarchy = new DefaultInputModuleHierarchy();
+  }
+
+  @Test
+  public void test() {
+    DefaultInputModule root = new DefaultInputModule("root");
+    DefaultInputModule mod1 = new DefaultInputModule("mod1");
+    DefaultInputModule mod2 = new DefaultInputModule("mod2");
+    DefaultInputModule mod3 = new DefaultInputModule("mod3");
+    DefaultInputModule mod4 = new DefaultInputModule("mod4");
+
+    moduleHierarchy.setRoot(root);
+    moduleHierarchy.index(mod1, root);
+    moduleHierarchy.index(mod2, mod1);
+    moduleHierarchy.index(mod3, root);
+    moduleHierarchy.index(mod4, root);
+
+    assertThat(moduleHierarchy.children(root)).containsOnly(mod1, mod3, mod4);
+    assertThat(moduleHierarchy.children(mod4)).isEmpty();
+    assertThat(moduleHierarchy.children(mod1)).containsOnly(mod2);
+
+    assertThat(moduleHierarchy.parent(mod4)).isEqualTo(root);
+    assertThat(moduleHierarchy.parent(mod2)).isEqualTo(mod1);
+    assertThat(moduleHierarchy.parent(mod1)).isEqualTo(root);
+    assertThat(moduleHierarchy.parent(root)).isNull();
+
+    assertThat(moduleHierarchy.root()).isEqualTo(root);
+  }
+}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/LanguageVerifierTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/LanguageVerifierTest.java
deleted file mode 100644 (file)
index e4af7a5..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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  02110-1301, USA.
- */
-package org.sonar.scanner.scan;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultFileSystem;
-import org.sonar.api.config.Settings;
-import org.sonar.api.config.MapSettings;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.utils.MessageException;
-import org.sonar.scanner.FakeJava;
-import org.sonar.scanner.repository.language.DefaultLanguagesRepository;
-import org.sonar.scanner.repository.language.LanguagesRepository;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class LanguageVerifierTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  private Settings settings = new MapSettings();
-  private LanguagesRepository languages = new DefaultLanguagesRepository(new Languages(FakeJava.INSTANCE));
-  private DefaultFileSystem fs;
-
-  @Before
-  public void prepare() throws Exception {
-    fs = new DefaultFileSystem(temp.newFolder().toPath());
-  }
-
-  @Test
-  public void language_is_not_set() {
-    LanguageVerifier verifier = new LanguageVerifier(settings, languages, fs);
-    verifier.start();
-
-    // no failure and no language is forced
-    assertThat(fs.languages()).isEmpty();
-
-    verifier.stop();
-  }
-
-  @Test
-  public void language_is_empty() {
-    settings.setProperty("sonar.language", "");
-    LanguageVerifier verifier = new LanguageVerifier(settings, languages, fs);
-    verifier.start();
-
-    // no failure and no language is forced
-    assertThat(fs.languages()).isEmpty();
-
-    verifier.stop();
-  }
-
-  @Test
-  public void language_is_valid() {
-    settings.setProperty("sonar.language", "java");
-
-    LanguageVerifier verifier = new LanguageVerifier(settings, languages, fs);
-    verifier.start();
-
-    // no failure and language is hardly registered
-    assertThat(fs.languages()).contains("java");
-
-    verifier.stop();
-  }
-
-  @Test
-  public void language_is_not_valid() {
-    thrown.expect(MessageException.class);
-    thrown.expectMessage("You must install a plugin that supports the language 'php'");
-
-    settings.setProperty("sonar.language", "php");
-    LanguageVerifier verifier = new LanguageVerifier(settings, languages, fs);
-    verifier.start();
-  }
-}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java
new file mode 100644 (file)
index 0000000..00d7c12
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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  02110-1301, USA.
+ */
+package org.sonar.scanner.scan;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.InputModule;
+import org.sonar.scanner.scan.filesystem.BatchIdGenerator;
+
+public class ModuleIndexerTest {
+  private ModuleIndexer indexer;
+  private DefaultComponentTree tree;
+  private DefaultInputModuleHierarchy moduleHierarchy;
+  private ImmutableProjectReactor reactor;
+
+  @Before
+  public void setUp() {
+    reactor = mock(ImmutableProjectReactor.class);
+    tree = new DefaultComponentTree();
+    moduleHierarchy = new DefaultInputModuleHierarchy();
+    indexer = new ModuleIndexer(reactor, tree, new BatchIdGenerator(), moduleHierarchy);
+  }
+
+  @Test
+  public void testIndex() {
+    ProjectDefinition root = ProjectDefinition.create().setKey("root");
+    ProjectDefinition mod1 = ProjectDefinition.create().setKey("mod1");
+    ProjectDefinition mod2 = ProjectDefinition.create().setKey("mod2");
+    ProjectDefinition mod3 = ProjectDefinition.create().setKey("mod3");
+    ProjectDefinition mod4 = ProjectDefinition.create().setKey("mod4");
+
+    root.addSubProject(mod1);
+    mod1.addSubProject(mod2);
+    root.addSubProject(mod3);
+    root.addSubProject(mod4);
+
+    when(reactor.getRoot()).thenReturn(root);
+    indexer.start();
+
+    InputModule rootModule = moduleHierarchy.root();
+    assertThat(rootModule).isNotNull();
+    assertThat(moduleHierarchy.children(rootModule)).hasSize(3);
+    assertThat(tree.getChildren(rootModule)).hasSize(3);
+  }
+}
index 38548c7370b99b58ba4394931009b8a515b72ef9..54445c639b3b4bccdb1200baee3be71291164eee 100644 (file)
@@ -21,24 +21,22 @@ package org.sonar.scanner.scan.filesystem;
 
 import org.junit.Test;
 import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.IndexedFile;
-import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.scan.filesystem.AdditionalFilePredicates;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import java.nio.file.Paths;
-
 public class AdditionalFilePredicatesTest {
 
   @Test
   public void key() {
     FilePredicate predicate = new AdditionalFilePredicates.KeyPredicate("struts:Action.java");
 
-    IndexedFile indexedFile = new DefaultIndexedFile("struts", Paths.get("module"), "Action.java");
-    assertThat(predicate.apply(indexedFile)).isTrue();
+    InputFile inputFile = new TestInputFileBuilder("struts", "Action.java").build();
+    assertThat(predicate.apply(inputFile)).isTrue();
 
-    indexedFile = new DefaultIndexedFile("struts", Paths.get("module"), "Filter.java");
-    assertThat(predicate.apply(indexedFile)).isFalse();
+    inputFile = new TestInputFileBuilder("struts", "Filter.java").build();
+    assertThat(predicate.apply(inputFile)).isFalse();
   }
 }
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileBuilderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileBuilderTest.java
new file mode 100644 (file)
index 0000000..b1c514f
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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  02110-1301, USA.
+ */
+package org.sonar.scanner.scan.filesystem;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.InputFile.Type;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.scan.filesystem.PathResolver;
+
+public class InputFileBuilderTest {
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  private Path baseDir;
+  private InputFileBuilder builder;
+
+  @Before
+  public void setUp() throws IOException {
+    baseDir = temp.newFolder().toPath();
+    DefaultInputModule module = new DefaultInputModule(ProjectDefinition.create()
+      .setKey("module1")
+      .setBaseDir(baseDir.toFile()), 0);
+
+    PathResolver pathResolver = new PathResolver();
+    LanguageDetection langDetection = mock(LanguageDetection.class);
+    MetadataGenerator metadataGenerator = mock(MetadataGenerator.class);
+    BatchIdGenerator idGenerator = new BatchIdGenerator();
+    builder = new InputFileBuilder(module, pathResolver, langDetection, metadataGenerator, idGenerator);
+  }
+
+  @Test
+  public void testBuild() {
+    Path filePath = baseDir.resolve("src/File1.xoo");
+    DefaultInputFile inputFile = builder.create(filePath, Type.MAIN, StandardCharsets.UTF_8);
+    
+    assertThat(inputFile.moduleKey()).isEqualTo("module1");
+    assertThat(inputFile.absolutePath()).isEqualTo(filePath.toString());
+    assertThat(inputFile.key()).isEqualTo("module1:src/File1.xoo");
+    assertThat(inputFile.publish()).isFalse();
+  }
+}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactoryTest.java
deleted file mode 100644 (file)
index 0064dd1..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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  02110-1301, USA.
- */
-package org.sonar.scanner.scan.filesystem;
-
-import org.junit.Test;
-import org.sonar.api.config.MapSettings;
-import org.sonar.api.resources.Languages;
-import org.sonar.scanner.FakeJava;
-import org.sonar.scanner.repository.language.DefaultLanguagesRepository;
-import org.sonar.scanner.repository.language.LanguagesRepository;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class LanguageDetectionFactoryTest {
-  @Test
-  public void testCreate() throws Exception {
-    LanguagesRepository languages = new DefaultLanguagesRepository(new Languages(FakeJava.INSTANCE));
-    LanguageDetectionFactory factory = new LanguageDetectionFactory(new MapSettings(), languages);
-    LanguageDetection languageDetection = factory.create();
-    assertThat(languageDetection).isNotNull();
-    assertThat(languageDetection.patternsByLanguage()).hasSize(1);
-    assertThat(languageDetection.patternsByLanguage().containsKey("java")).isTrue();
-  }
-}
index 874351ee3e0ff712bc5cb3878e7e3ee93b53d725..c9ab6444c4263192c8d0e5a1a902aed3927a8a1c 100644 (file)
@@ -123,7 +123,7 @@ public class LanguageDetectionTest {
   @Test
   public void fail_if_invalid_language() {
     thrown.expect(MessageException.class);
-    thrown.expectMessage("No language is installed with key 'unknown'. Please update property 'sonar.language'");
+    thrown.expectMessage("You must install a plugin that supports the language 'unknown'");
 
     LanguagesRepository languages = new DefaultLanguagesRepository(new Languages(new MockLanguage("java", "java"), new MockLanguage("php", "php")));
     Settings settings = new MapSettings();
index 73f0dc3c8f7cf323b0a6b2bfbb8686ff70f83029..e752025b0b6fd36a2ca14deb9336d40aa592c0bc 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.scanner.scan.filesystem;
 
 import org.junit.Test;
 import org.mockito.Mockito;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.FileMetadata;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -32,6 +33,6 @@ public class MetadataGeneratorProviderTest {
     StatusDetectionFactory statusDetectionFactory = mock(StatusDetectionFactory.class, Mockito.RETURNS_MOCKS);
 
     MetadataGeneratorProvider factory = new MetadataGeneratorProvider();
-    assertThat(factory.provide(statusDetectionFactory, new FileMetadata())).isNotNull();
+    assertThat(factory.provide(new DefaultInputModule("module"), statusDetectionFactory, new FileMetadata())).isNotNull();
   }
 }
index 17f7f61a27a67e36d4d5ccf65c4bcd7ad57b436c..9826ce2c4ab8bcd77dd2e552b4ceb2b25e686f1f 100644 (file)
 package org.sonar.scanner.scan.filesystem;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-import java.io.File;
-import java.io.FileNotFoundException;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 
 import org.apache.commons.io.FileUtils;
 import org.junit.Assert;
@@ -37,13 +35,10 @@ import org.junit.rules.TemporaryFolder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.FileMetadata;
-import org.sonar.api.batch.fs.internal.Metadata;
 import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
-import org.sonar.api.config.MapSettings;
-import org.sonar.api.scan.filesystem.PathResolver;
 import org.sonar.api.utils.PathUtils;
 
 public class MetadataGeneratorTest {
@@ -54,106 +49,70 @@ public class MetadataGeneratorTest {
   private StatusDetection statusDetection;
   @Mock
   private DefaultModuleFileSystem fs;
-  @Mock
-  private FileMetadata metadata;
 
-  private MetadataGenerator builder;
+  private FileMetadata metadata;
+  private MetadataGenerator generator;
 
   @Before
   public void setUp() {
     MockitoAnnotations.initMocks(this);
-    builder = new MetadataGenerator(statusDetection, metadata);
-    // TODO
+    metadata = new FileMetadata();
+    generator = new MetadataGenerator(new DefaultInputModule("module"), statusDetection, metadata);
+  }
+
+  @Test
+  public void should_detect_charset_from_BOM() {
+    Path basedir = Paths.get("src/test/resources/org/sonar/scanner/scan/filesystem/");
+
+    assertThat(createInputFileWithMetadata(generator, basedir, "without_BOM.txt").charset())
+      .isEqualTo(StandardCharsets.US_ASCII);
+    assertThat(createInputFileWithMetadata(generator, basedir, "UTF-8.txt").charset())
+      .isEqualTo(StandardCharsets.UTF_8);
+    assertThat(createInputFileWithMetadata(generator, basedir, "UTF-16BE.txt").charset())
+      .isEqualTo(StandardCharsets.UTF_16BE);
+    assertThat(createInputFileWithMetadata(generator, basedir, "UTF-16LE.txt").charset())
+      .isEqualTo(StandardCharsets.UTF_16LE);
+    assertThat(createInputFileWithMetadata(generator, basedir, "UTF-32BE.txt").charset())
+      .isEqualTo(MetadataGenerator.UTF_32BE);
+    assertThat(createInputFileWithMetadata(generator, basedir, "UTF-32LE.txt").charset())
+      .isEqualTo(MetadataGenerator.UTF_32LE);
+
+    try {
+      createInputFileWithMetadata(generator, basedir, "non_existing");
+      Assert.fail();
+    } catch (IllegalStateException e) {
+      assertThat(e.getMessage()).endsWith("Unable to read file " + basedir.resolve("non_existing").toAbsolutePath());
+      assertThat(e.getCause()).isInstanceOf(IllegalStateException.class);
+    }
+  }
+
+  private DefaultInputFile createInputFileWithMetadata(MetadataGenerator generator, Path baseDir, String relativePath) {
+    DefaultInputFile inputFile = new TestInputFileBuilder("struts", relativePath)
+      .setModuleBaseDir(baseDir)
+      .build();
+    generator.setMetadata(inputFile, StandardCharsets.US_ASCII);
+    return inputFile;
+  }
+
+  @Test
+  public void complete_input_file() throws Exception {
+    // file system
+    Path baseDir = temp.newFolder().toPath();
+    Path srcFile = baseDir.resolve("src/main/java/foo/Bar.java");
+    FileUtils.touch(srcFile.toFile());
+    FileUtils.write(srcFile.toFile(), "single line");
+
+    // status
+    when(statusDetection.status("foo", "src/main/java/foo/Bar.java", "6c1d64c0b3555892fe7273e954f6fb5a"))
+      .thenReturn(InputFile.Status.ADDED);
+
+    InputFile inputFile = createInputFileWithMetadata(generator, baseDir, "src/main/java/foo/Bar.java");
+
+    assertThat(inputFile.type()).isEqualTo(InputFile.Type.MAIN);
+    assertThat(inputFile.file()).isEqualTo(srcFile.toFile());
+    assertThat(inputFile.absolutePath()).isEqualTo(PathUtils.sanitize(srcFile.toAbsolutePath().toString()));
+    assertThat(inputFile.key()).isEqualTo("struts:src/main/java/foo/Bar.java");
+    assertThat(inputFile.relativePath()).isEqualTo("src/main/java/foo/Bar.java");
+    assertThat(inputFile.lines()).isEqualTo(1);
   }
-  /*
-   * @Test
-   * public void should_detect_charset_from_BOM() {
-   * File basedir = new File("src/test/resources/org/sonar/scanner/scan/filesystem/");
-   * when(fs.baseDir()).thenReturn(basedir);
-   * when(fs.encoding()).thenReturn(StandardCharsets.US_ASCII);
-   * 
-   * assertThat(createAndComplete(builder, new File(basedir, "without_BOM.txt")).charset())
-   * .isEqualTo(StandardCharsets.US_ASCII);
-   * assertThat(createAndComplete(builder, new File(basedir, "UTF-8.txt")).charset())
-   * .isEqualTo(StandardCharsets.UTF_8);
-   * assertThat(createAndComplete(builder, new File(basedir, "UTF-16BE.txt")).charset())
-   * .isEqualTo(StandardCharsets.UTF_16BE);
-   * assertThat(createAndComplete(builder, new File(basedir, "UTF-16LE.txt")).charset())
-   * .isEqualTo(StandardCharsets.UTF_16LE);
-   * assertThat(createAndComplete(builder, new File(basedir, "UTF-32BE.txt")).charset())
-   * .isEqualTo(InputFileBuilder.UTF_32BE);
-   * assertThat(createAndComplete(builder, new File(basedir, "UTF-32LE.txt")).charset())
-   * .isEqualTo(InputFileBuilder.UTF_32LE);
-   * 
-   * try {
-   * createAndComplete(builder, new File(basedir, "non_existing"));
-   * Assert.fail();
-   * } catch (IllegalStateException e) {
-   * assertThat(e.getMessage()).isEqualTo("Unable to read file " + new File(basedir, "non_existing").getAbsolutePath());
-   * assertThat(e.getCause()).isInstanceOf(FileNotFoundException.class);
-   * }
-   * }
-   * 
-   * private static DefaultInputFile createAndComplete(InputFileBuilder builder, File file) {
-   * DefaultInputFile inputFile = new TestInputFileBuilder("module", file.toString())
-   * .setMetadata()
-   * .build();
-   * return inputFile;
-   * }
-   * 
-   * @Test
-   * public void complete_input_file() throws Exception {
-   * // file system
-   * File basedir = temp.newFolder();
-   * File srcFile = new File(basedir, "src/main/java/foo/Bar.java");
-   * FileUtils.touch(srcFile);
-   * FileUtils.write(srcFile, "single line");
-   * when(fs.baseDir()).thenReturn(basedir);
-   * when(fs.encoding()).thenReturn(StandardCharsets.UTF_8);
-   * 
-   * // status
-   * when(statusDetection.status("foo", "src/main/java/foo/Bar.java", "6c1d64c0b3555892fe7273e954f6fb5a"))
-   * .thenReturn(InputFile.Status.ADDED);
-   * 
-   * Metadata metadata = builder.readMetadata(srcFile);
-   * builder.readMetadata(inputFile);
-   * 
-   * assertThat(inputFile.type()).isEqualTo(InputFile.Type.MAIN);
-   * assertThat(inputFile.file()).isEqualTo(srcFile.getAbsoluteFile());
-   * assertThat(inputFile.absolutePath()).isEqualTo(PathUtils.sanitize(srcFile.getAbsolutePath()));
-   * assertThat(inputFile.language()).isEqualTo("java");
-   * assertThat(inputFile.key()).isEqualTo("struts:src/main/java/foo/Bar.java");
-   * assertThat(inputFile.relativePath()).isEqualTo("src/main/java/foo/Bar.java");
-   * assertThat(inputFile.lines()).isEqualTo(1);
-   * }
-   * 
-   * @Test
-   * public void set_metadata() throws Exception {
-   * DefaultInputFile inputFile = new TestInputFileBuilder("module", "src/main/java/foo/Bar.java").build();
-   * when()
-   * 
-   * Metadata metadata = builder.readMetadata(inputFile);
-   * 
-   * }
-   * 
-   * @Test
-   * public void return_null_if_language_not_detected() throws Exception {
-   * // file system
-   * File basedir = temp.newFolder();
-   * File srcFile = new File(basedir, "src/main/java/foo/Bar.java");
-   * FileUtils.touch(srcFile);
-   * FileUtils.write(srcFile, "single line");
-   * when(fs.baseDir()).thenReturn(basedir);
-   * when(fs.encoding()).thenReturn(StandardCharsets.UTF_8);
-   * 
-   * // lang
-   * when(langDetection.language(any(DefaultIndexedFile.class))).thenReturn(null);
-   * 
-   * InputFileBuilder builder = new InputFileBuilder(statusDetection, fs, new FileMetadata());
-   * DefaultInputFile inputFile = builder.create(srcFile);
-   * inputFile = builder.completeAndComputeMetadata(inputFile, InputFile.Type.MAIN);
-   * 
-   * assertThat(inputFile).isNull();
-   * }
-   */
 }
index 2918d4fd5e6a8f21b11ccf616075eeccad86cec5..01cce65f39530be390638a1ffd43095ea045150b 100644 (file)
@@ -82,7 +82,7 @@ public class JSONReportTest {
     SIMPLE_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+02:00"));
     when(server.getVersion()).thenReturn("3.6");
 
-    DefaultInputDir inputDir = new DefaultInputDir("struts", "src/main/java/org/apache/struts", TestInputFileBuilder.batchId++);
+    DefaultInputDir inputDir = new DefaultInputDir("struts", "src/main/java/org/apache/struts", TestInputFileBuilder.nextBatchId());
     DefaultInputFile inputFile = new TestInputFileBuilder("struts", "src/main/java/org/apache/struts/Action.java").build();
     inputFile.setStatus(InputFile.Status.CHANGED);
     InputComponentStore fileCache = mock(InputComponentStore.class);
index 4d11247c5d4036afd8c536b3e8683e9ef8a2a872..400c16eef420e90cc7bdcdedf997704bc95e945a 100644 (file)
@@ -37,8 +37,6 @@ import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
 import org.sonar.api.config.MapSettings;
 import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Resource;
 import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.core.metric.ScannerMetrics;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
@@ -105,7 +103,6 @@ public class DefaultSensorStorageTest {
     InputFile file = new TestInputFileBuilder("foo", "src/Foo.php").build();
 
     ArgumentCaptor<DefaultMeasure> argumentCaptor = ArgumentCaptor.forClass(DefaultMeasure.class);
-    Resource sonarFile = File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php");
     when(measureCache.put(eq(file.key()), eq(CoreMetrics.NCLOC_KEY), argumentCaptor.capture())).thenReturn(null);
     underTest.store(new DefaultMeasure()
       .on(file)
index 5d408aef691a77b34a1ff30b6e9f10096c94f784..34fbc34a9b0334a3055586d765f1c04b16dc0b9d 100644 (file)
@@ -78,4 +78,8 @@ public class FileStructure {
   public File contextProperties() {
     return new File(dir, "context-props.pb");
   }
+  
+  public File root() {
+    return dir;
+  }
 }