]> source.dussan.org Git - sonarqube.git/commitdiff
Restore old behavior for InputFile::lines() -> returns 1 for empty files
authorJulien HENRY <julien.henry@sonarsource.com>
Mon, 13 Apr 2015 09:59:54 +0000 (11:59 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Mon, 13 Apr 2015 09:59:54 +0000 (11:59 +0200)
sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java
sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java
sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseLessPhaseExecutor.java
sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java
sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/preview/EmptyFileTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.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/FileMetadata.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/FileMetadataTest.java

index 978dbdb96437ceea8ee41a3bf445e7298bb099e5..53950bec4798071994a4a6c7828b91a4be2acb55 100644 (file)
@@ -31,13 +31,12 @@ import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.*;
 import org.sonar.batch.protocol.output.BatchReport.Range;
 import org.sonar.batch.protocol.output.BatchReport.Scm;
 import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
 import org.sonar.batch.protocol.output.BatchReport.Symbols;
 import org.sonar.batch.protocol.output.BatchReport.SyntaxHighlighting;
-import org.sonar.batch.protocol.output.BatchReportReader;
 import org.sonar.batch.report.BatchReportUtils;
 import org.sonar.batch.report.ReportPublisher;
 import org.sonar.batch.scan.measure.MeasureCache;
@@ -73,7 +72,9 @@ public class SourceDataFactory implements BatchComponent {
 
   public byte[] consolidateData(DefaultInputFile inputFile) throws IOException {
     FileSourceDb.Data.Builder dataBuilder = createForSource(inputFile);
-    applyLineMeasures(inputFile, dataBuilder);
+    if (!inputFile.isEmpty()) {
+      applyLineMeasures(inputFile, dataBuilder);
+    }
     applyScm(inputFile, dataBuilder);
     applyDuplications(inputFile.key(), dataBuilder);
     applyHighlighting(inputFile, dataBuilder);
index a55562c88f2f5a1414c5172292e63384fe123daf..d1defb7b7ca9372aed539c9c149cd15ab1570154 100644 (file)
  */
 package org.sonar.batch.index;
 
-import org.sonar.api.batch.fs.internal.FileMetadata;
-import org.sonar.api.batch.fs.internal.FileMetadata.LineHashConsumer;
-
 import org.apache.commons.codec.binary.Hex;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.ibatis.session.ResultContext;
 import org.apache.ibatis.session.ResultHandler;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.api.batch.fs.internal.FileMetadata.LineHashConsumer;
 import org.sonar.api.utils.System2;
 import org.sonar.batch.ProjectTree;
 import org.sonar.batch.scan.filesystem.InputPathCache;
@@ -126,9 +125,6 @@ public class SourcePersister implements ScanPersister {
 
   @CheckForNull
   private String lineHashesAsMd5Hex(DefaultInputFile f) {
-    if (f.lines() == 0) {
-      return null;
-    }
     // A md5 string is 32 char long + '\n' = 33
     final StringBuilder result = new StringBuilder(f.lines() * (32 + 1));
 
index 644cf8bf724dfbb6160ccd6853a8875da2083f90..e116bb8056587915a7e801e1ad9f2b9c1d81b6ba 100644 (file)
@@ -47,12 +47,12 @@ public final class DatabaseLessPhaseExecutor implements PhaseExecutor {
   private final IssueExclusionsLoader issueExclusionsLoader;
   private final IssuesReports issuesReport;
   private final LocalIssueTracking localIssueTracking;
-  private final ReportPublisher publishReportJob;
+  private final ReportPublisher reportPublisher;
 
   public DatabaseLessPhaseExecutor(Phases phases, InitializersExecutor initializersExecutor, SensorsExecutor sensorsExecutor,
     SensorContext sensorContext, DefaultIndex index,
     EventBus eventBus, ProjectInitializer pi, FileSystemLogger fsLogger, IssuesReports jsonReport, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
-    IssueExclusionsLoader issueExclusionsLoader, LocalIssueTracking localIssueTracking, ReportPublisher publishReportJob) {
+    IssueExclusionsLoader issueExclusionsLoader, LocalIssueTracking localIssueTracking, ReportPublisher reportPublisher) {
     this.phases = phases;
     this.initializersExecutor = initializersExecutor;
     this.sensorsExecutor = sensorsExecutor;
@@ -66,7 +66,7 @@ public final class DatabaseLessPhaseExecutor implements PhaseExecutor {
     this.profileVerifier = profileVerifier;
     this.issueExclusionsLoader = issueExclusionsLoader;
     this.localIssueTracking = localIssueTracking;
-    this.publishReportJob = publishReportJob;
+    this.reportPublisher = reportPublisher;
   }
 
   /**
@@ -106,7 +106,7 @@ public final class DatabaseLessPhaseExecutor implements PhaseExecutor {
   private void publishReportJob() {
     String stepName = "Publish report";
     eventBus.fireEvent(new BatchStepEvent(stepName, true));
-    this.publishReportJob.execute();
+    this.reportPublisher.execute();
     eventBus.fireEvent(new BatchStepEvent(stepName, false));
   }
 
index 657a58083f2c58b36a398f481a48af83e8272fd5..7d01ad44a3c687689cafcb3bd16129101d663db6 100644 (file)
@@ -49,7 +49,7 @@ public final class DatabaseModePhaseExecutor implements PhaseExecutor {
   private final PostJobsExecutor postJobsExecutor;
   private final InitializersExecutor initializersExecutor;
   private final SensorsExecutor sensorsExecutor;
-  private final ReportPublisher publishReportJob;
+  private final ReportPublisher reportPublisher;
   private final SensorContext sensorContext;
   private final DefaultIndex index;
   private final ProjectInitializer pi;
@@ -66,7 +66,7 @@ public final class DatabaseModePhaseExecutor implements PhaseExecutor {
   public DatabaseModePhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor,
     InitializersExecutor initializersExecutor, PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
     SensorContext sensorContext, DefaultIndex index,
-    EventBus eventBus, ReportPublisher publishReportJob, ProjectInitializer pi,
+    EventBus eventBus, ReportPublisher reportPublisher, ProjectInitializer pi,
     ScanPersister[] persisters, FileSystemLogger fsLogger, IssuesReports jsonReport, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
     IssueExclusionsLoader issueExclusionsLoader, DefaultAnalysisMode analysisMode, DatabaseSession session, ResourcePersister resourcePersister) {
     this.phases = phases;
@@ -77,7 +77,7 @@ public final class DatabaseModePhaseExecutor implements PhaseExecutor {
     this.sensorContext = sensorContext;
     this.index = index;
     this.eventBus = eventBus;
-    this.publishReportJob = publishReportJob;
+    this.reportPublisher = reportPublisher;
     this.pi = pi;
     this.persisters = persisters;
     this.fsLogger = fsLogger;
@@ -168,7 +168,7 @@ public final class DatabaseModePhaseExecutor implements PhaseExecutor {
   private void publishReportJob() {
     String stepName = "Publish report";
     eventBus.fireEvent(new BatchStepEvent(stepName, true));
-    this.publishReportJob.execute();
+    this.reportPublisher.execute();
     eventBus.fireEvent(new BatchStepEvent(stepName, false));
   }
 
index 941f7d42f617527d0ca3d2c76ed9458b2c381b71..51365f6d5c64d266727bc648e6fbd8ec23f8b209 100644 (file)
@@ -106,7 +106,7 @@ public final class ScmSensor implements Sensor {
   }
 
   private void addIfNotEmpty(List<InputFile> filesToBlame, InputFile f) {
-    if (f.lines() > 0) {
+    if (!f.isEmpty()) {
       filesToBlame.add(f);
     }
   }
index 62ea53ce6aeabbf8973b7a809d241f76d77d7aa6..ac5d983c1e9ceab461b8def6f326d58474866e44 100644 (file)
@@ -84,7 +84,7 @@ public class EmptyFileTest {
       .property("sonar.xoo.internalKey", "my/internal/key")
       .start();
 
-    assertThat(result.issues()).hasSize(10);
+    assertThat(result.issues()).hasSize(11);
   }
 
 }
index 4e0af79ccc7233743d938a40adb0edd0312c234c..d98180bf41709edde0827c0af5120193d6640c0b 100644 (file)
@@ -105,11 +105,17 @@ public interface InputFile extends InputPath {
   Status status();
 
   /**
-   * Number of physical lines. This method supports all end-of-line characters. Returns
-   * zero if the file is empty.
+   * Number of physical lines. This method supports all end-of-line characters. Formula is (number of line break + 1). Returns
+   * 1 if the file is empty.</br> Returns 2 for <tt>foo\nbar</tt>. Returns 3 for <tt>foo\nbar\n</tt>.
    */
   int lines();
 
+  /**
+   * Check if the file content is empty (ignore potential BOM).
+   * @since 5.2
+   */
+  boolean isEmpty();
+
   /**
    * Return a {@link TextPointer} in the given file.
    * @param line Line of the pointer. Start at 1.
index 4f89a1c0dd32cde0f90a3af71cd64f76bda6c57d..5190bb1a0f1844114da6229b54e3d04bafab5a15 100644 (file)
@@ -104,6 +104,11 @@ public class DefaultInputFile implements InputFile {
     return lines;
   }
 
+  @Override
+  public boolean isEmpty() {
+    return lastValidOffset == 0;
+  }
+
   /**
    * Component key.
    */
index cb5ea5660af0c920fbab3d51ba0ecec45f9ae1d1..fa894077be402c35c2963919542cdeeb6eed9334 100644 (file)
@@ -66,7 +66,7 @@ public class FileMetadata implements BatchComponent {
   }
 
   private static class LineCounter extends CharHandler {
-    private int lines = 0;
+    private int lines = 1;
     private int nonBlankLines = 0;
     private boolean blankLine = true;
     boolean alreadyLoggedInvalidCharacter = false;
@@ -80,9 +80,6 @@ public class FileMetadata implements BatchComponent {
 
     @Override
     protected void handleAll(char c) {
-      if (this.lines == 0) {
-        this.lines = 1;
-      }
       if (!alreadyLoggedInvalidCharacter && c == '\ufffd') {
         LOG.warn("Invalid character encountered in file {} at line {} for encoding {}. Please fix file content or configure the encoding to be used using property '{}'.", file,
           lines, encoding, CoreProperties.ENCODING_PROPERTY);
@@ -156,19 +153,12 @@ public class FileMetadata implements BatchComponent {
     private final MessageDigest lineMd5Digest = DigestUtils.getMd5Digest();
     private final StringBuilder sb = new StringBuilder();
     private final LineHashConsumer consumer;
-    private int line = 0;
+    private int line = 1;
 
     public LineHashComputer(LineHashConsumer consumer) {
       this.consumer = consumer;
     }
 
-    @Override
-    protected void handleAll(char c) {
-      if (this.line == 0) {
-        this.line = 1;
-      }
-    }
-
     @Override
     protected void handleIgnoreEoL(char c) {
       if (!Character.isWhitespace(c)) {
index 9e06a3e9e5c88b4275c4a0213f5d9c57c1238622..e26451cf82d0c1da03faf9d1066186e56a4a8631 100644 (file)
@@ -56,7 +56,7 @@ public class FileMetadataTest {
     FileUtils.touch(tempFile);
 
     FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
-    assertThat(metadata.lines).isEqualTo(0);
+    assertThat(metadata.lines).isEqualTo(1);
     assertThat(metadata.nonBlankLines).isEqualTo(0);
     assertThat(metadata.hash).isNotEmpty();
     assertThat(metadata.originalLineOffsets).containsOnly(0);
@@ -219,6 +219,8 @@ public class FileMetadataTest {
           case 3:
             assertThat(Hex.encodeHexString(hash)).isEqualTo(md5Hex("baz"));
             break;
+          default:
+            fail("Invalid line");
         }
       }
     });
@@ -236,7 +238,13 @@ public class FileMetadataTest {
 
       @Override
       public void consume(int lineIdx, @Nullable byte[] hash) {
-        fail("File is empty and should not report any line hash");
+        switch (lineIdx) {
+          case 1:
+            assertThat(hash).isNull();
+            break;
+          default:
+            fail("Invalid line");
+        }
       }
     });
   }