aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-11-20 12:00:50 +0100
committerJulien HENRY <julien.henry@sonarsource.com>2014-11-20 12:01:35 +0100
commitd10e163a67923e10247aa242b7463122e7e5b92c (patch)
treeb8d8f0a4cbfb78fd6ef9db3e68c09b514b86df39 /sonar-batch
parente6cf1274907bad79ea45014041f8716a460bb99d (diff)
downloadsonarqube-d10e163a67923e10247aa242b7463122e7e5b92c.tar.gz
sonarqube-d10e163a67923e10247aa242b7463122e7e5b92c.zip
SONAR-5827 Fix corner cases with highligthing offset conversion
Diffstat (limited to 'sonar-batch')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRule.java5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java102
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/index/SourcePersisterTest.java83
4 files changed, 143 insertions, 56 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java
index 121a6683bca..da5166a9753 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java
@@ -19,11 +19,10 @@
*/
package org.sonar.batch.highlighting;
-import com.google.common.collect.Sets;
-import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Ordering;
+import com.google.common.collect.Sets;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import javax.annotation.Nullable;
@@ -38,10 +37,10 @@ public class SyntaxHighlightingDataBuilder {
syntaxHighlightingRuleSet = Sets.newTreeSet(new Ordering<SyntaxHighlightingRule>() {
@Override
public int compare(@Nullable SyntaxHighlightingRule left,
- @Nullable SyntaxHighlightingRule right) {
+ @Nullable SyntaxHighlightingRule right) {
int result = left.getStartPosition() - right.getStartPosition();
if (result == 0) {
- result = left.getEndPosition() - right.getEndPosition();
+ result = right.getEndPosition() - left.getEndPosition();
}
return result;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRule.java b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRule.java
index bcfab67f476..81016289477 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRule.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRule.java
@@ -50,4 +50,9 @@ public class SyntaxHighlightingRule implements Serializable {
public TypeOfText getTextType() {
return textType;
}
+
+ @Override
+ public String toString() {
+ return "" + startPosition + "," + endPosition + "," + textType.cssClass();
+ }
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java
index 93c516a37f9..04fb4bc6694 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java
@@ -113,28 +113,8 @@ public class SourcePersister implements ScanPersister {
for (InputPath inputPath : inputPathCache.all()) {
if (inputPath instanceof InputFile) {
- DefaultInputFile inputFile = (DefaultInputFile) inputPath;
- org.sonar.api.resources.File file = (org.sonar.api.resources.File) resourceCache.get(inputFile.key());
- String fileUuid = file.getUuid();
- FileSourceDto previous = mapper.select(fileUuid);
- String newData = getSourceData(inputFile);
- String dataHash = newData != null ? DigestUtils.md5Hex(newData) : "0";
- Date now = system2.newDate();
- if (previous == null) {
- FileSourceDto newFileSource = new FileSourceDto().setProjectUuid(projectTree.getRootProject().getUuid()).setFileUuid(fileUuid).setData(newData).setDataHash(dataHash)
- .setCreatedAt(now)
- .setUpdatedAt(now);
- mapper.insert(newFileSource);
- } else {
- if (dataHash.equals(previous.getDataHash())) {
- continue;
- } else {
- previous.setData(newData).setDataHash(dataHash).setUpdatedAt(now);
- mapper.update(previous);
- }
- }
+ persist(session, mapper, inputPath);
}
- session.commit();
}
} catch (Exception e) {
throw new IllegalStateException("Unable to save file sources", e);
@@ -144,6 +124,29 @@ public class SourcePersister implements ScanPersister {
}
+ private void persist(DbSession session, FileSourceMapper mapper, InputPath inputPath) {
+ DefaultInputFile inputFile = (DefaultInputFile) inputPath;
+ org.sonar.api.resources.File file = (org.sonar.api.resources.File) resourceCache.get(inputFile.key());
+ String fileUuid = file.getUuid();
+ FileSourceDto previous = mapper.select(fileUuid);
+ String newData = getSourceData(inputFile);
+ String dataHash = newData != null ? DigestUtils.md5Hex(newData) : "0";
+ Date now = system2.newDate();
+ if (previous == null) {
+ FileSourceDto newFileSource = new FileSourceDto().setProjectUuid(projectTree.getRootProject().getUuid()).setFileUuid(fileUuid).setData(newData).setDataHash(dataHash)
+ .setCreatedAt(now)
+ .setUpdatedAt(now);
+ mapper.insert(newFileSource);
+ session.commit();
+ } else {
+ if (!dataHash.equals(previous.getDataHash())) {
+ previous.setData(newData).setDataHash(dataHash).setUpdatedAt(now);
+ mapper.update(previous);
+ session.commit();
+ }
+ }
+ }
+
@CheckForNull
String getSourceData(DefaultInputFile file) {
if (file.lines() == 0) {
@@ -176,36 +179,50 @@ public class SourcePersister implements ScanPersister {
}
String[] computeHighlightingPerLine(DefaultInputFile file, @Nullable SyntaxHighlightingData highlighting) {
- String[] highlightingPerLine = new String[file.lines()];
+ String[] result = new String[file.lines()];
if (highlighting == null) {
- return highlightingPerLine;
+ return result;
}
Iterable<SyntaxHighlightingRule> rules = highlighting.syntaxHighlightingRuleSet();
int currentLineIdx = 1;
- StringBuilder currentLineSb = new StringBuilder();
+ StringBuilder[] highlightingPerLine = new StringBuilder[file.lines()];
for (SyntaxHighlightingRule rule : rules) {
- long ruleStartOffset = rule.getStartPosition();
- long ruleEndOffset = rule.getEndPosition();
- while (currentLineIdx < file.lines() && ruleStartOffset >= file.originalLineOffsets()[currentLineIdx]) {
+ while (currentLineIdx < file.lines() && rule.getStartPosition() >= file.originalLineOffsets()[currentLineIdx]) {
// This rule starts on another line so advance
- saveLineHighlighting(highlightingPerLine, currentLineIdx, currentLineSb);
currentLineIdx++;
}
// Now we know current rule starts on current line
- long ruleStartOffsetCurrentLine = ruleStartOffset;
- while (currentLineIdx < file.lines() && ruleEndOffset >= file.originalLineOffsets()[currentLineIdx]) {
- // rule continue on next line so write current line and continue on next line with same rule
- writeRule(currentLineSb, ruleStartOffsetCurrentLine - file.originalLineOffsets()[currentLineIdx - 1], file.originalLineOffsets()[currentLineIdx] - 1, rule.getTextType());
- saveLineHighlighting(highlightingPerLine, currentLineIdx, currentLineSb);
- currentLineIdx++;
- ruleStartOffsetCurrentLine = file.originalLineOffsets()[currentLineIdx];
- }
- // Rule ends on current line
- writeRule(currentLineSb, ruleStartOffsetCurrentLine - file.originalLineOffsets()[currentLineIdx - 1], ruleEndOffset - file.originalLineOffsets()[currentLineIdx - 1],
+ writeRule(file, rule, highlightingPerLine, currentLineIdx);
+ }
+ for (int i = 0; i < file.lines(); i++) {
+ result[i] = highlightingPerLine[i] != null ? highlightingPerLine[i].toString() : null;
+ }
+ return result;
+ }
+
+ private void writeRule(DefaultInputFile file, SyntaxHighlightingRule rule, StringBuilder[] highlightingPerLine, int currentLineIdx) {
+ // We know current rule starts on current line
+ long ruleStartOffsetCurrentLine = rule.getStartPosition();
+ while (currentLineIdx < file.lines() && rule.getEndPosition() >= file.originalLineOffsets()[currentLineIdx]) {
+ // rule continue on next line so write current line and continue on next line with same rule
+ writeRule(highlightingPerLine, currentLineIdx, ruleStartOffsetCurrentLine - file.originalLineOffsets()[currentLineIdx - 1], file.originalLineOffsets()[currentLineIdx]
+ - file.originalLineOffsets()[currentLineIdx - 1],
rule.getTextType());
+ currentLineIdx++;
+ ruleStartOffsetCurrentLine = file.originalLineOffsets()[currentLineIdx - 1];
}
- saveLineHighlighting(highlightingPerLine, currentLineIdx, currentLineSb);
- return highlightingPerLine;
+ // Rule ends on current line
+ writeRule(highlightingPerLine, currentLineIdx, ruleStartOffsetCurrentLine - file.originalLineOffsets()[currentLineIdx - 1], rule.getEndPosition()
+ - file.originalLineOffsets()[currentLineIdx - 1],
+ rule.getTextType());
+ }
+
+ private void writeRule(StringBuilder[] highlightingPerLine, int currentLineIdx, long startLineOffset, long endLineOffset, TypeOfText textType) {
+ if (highlightingPerLine[currentLineIdx - 1] == null) {
+ highlightingPerLine[currentLineIdx - 1] = new StringBuilder();
+ }
+ StringBuilder currentLineSb = highlightingPerLine[currentLineIdx - 1];
+ writeRule(currentLineSb, startLineOffset, endLineOffset, textType);
}
private void writeRule(StringBuilder currentLineSb, long startLineOffset, long endLineOffset, TypeOfText textType) {
@@ -219,11 +236,6 @@ public class SourcePersister implements ScanPersister {
.append(textType.cssClass());
}
- private void saveLineHighlighting(String[] highlightingPerLine, int currentLineIdx, StringBuilder currentLineSb) {
- highlightingPerLine[currentLineIdx - 1] = currentLineSb.toString();
- currentLineSb.setLength(0);
- }
-
private Map<Integer, String> getLineMetric(DefaultInputFile file, String metricKey) {
Map<Integer, String> authorsByLine;
Iterator<Measure> authorsIt = measureCache.byMetric(file.key(), metricKey).iterator();
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/SourcePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/SourcePersisterTest.java
index 81e96a2627e..18bf6bed889 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/index/SourcePersisterTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/index/SourcePersisterTest.java
@@ -37,7 +37,7 @@ import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
import org.sonar.batch.ProjectTree;
import org.sonar.batch.highlighting.SyntaxHighlightingData;
-import org.sonar.batch.highlighting.SyntaxHighlightingRule;
+import org.sonar.batch.highlighting.SyntaxHighlightingDataBuilder;
import org.sonar.batch.scan.filesystem.InputPathCache;
import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.core.persistence.AbstractDaoTestCase;
@@ -48,6 +48,7 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
+import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
@@ -188,11 +189,11 @@ public class SourcePersisterTest extends AbstractDaoTestCase {
when(measureCache.byMetric(PROJECT_KEY + ":" + relativePathNew, CoreMetrics.SCM_REVISIONS_BY_LINE_KEY))
.thenReturn(Arrays.asList(new Measure(CoreMetrics.SCM_REVISIONS_BY_LINE, "1=123;2=234;3=345")));
- SyntaxHighlightingData highlighting = new SyntaxHighlightingData(Arrays.asList(
- SyntaxHighlightingRule.create(0, 3, TypeOfText.ANNOTATION),
- SyntaxHighlightingRule.create(4, 5, TypeOfText.COMMENT),
- SyntaxHighlightingRule.create(7, 16, TypeOfText.CONSTANT)
- ));
+ SyntaxHighlightingData highlighting = new SyntaxHighlightingDataBuilder()
+ .registerHighlightingRule(0, 3, TypeOfText.ANNOTATION)
+ .registerHighlightingRule(4, 5, TypeOfText.COMMENT)
+ .registerHighlightingRule(7, 16, TypeOfText.CONSTANT)
+ .build();
when(componentDataCache.getData(PROJECT_KEY + ":" + relativePathNew, SnapshotDataTypes.SYNTAX_HIGHLIGHTING))
.thenReturn(highlighting);
@@ -200,6 +201,76 @@ public class SourcePersisterTest extends AbstractDaoTestCase {
checkTables("testPersistNewFileWithScmAndHighlighting", "file_sources");
}
+ @Test
+ public void testSimpleConversionOfHighlightingOffset() {
+ DefaultInputFile file = new DefaultInputFile(PROJECT_KEY, "src/foo.java")
+ .setLines(3)
+ .setOriginalLineOffsets(new long[] {0, 4, 7});
+
+ SyntaxHighlightingData highlighting = new SyntaxHighlightingDataBuilder()
+ .registerHighlightingRule(0, 3, TypeOfText.ANNOTATION)
+ .registerHighlightingRule(4, 5, TypeOfText.COMMENT)
+ .registerHighlightingRule(7, 16, TypeOfText.CONSTANT)
+ .build();
+
+ String[] highlightingPerLine = sourcePersister.computeHighlightingPerLine(file, highlighting);
+
+ assertThat(highlightingPerLine).containsOnly("0,3,a", "0,1,cd", "0,9,c");
+ }
+
+ @Test
+ public void testConversionOfHighlightingOffsetMultiLine() {
+ DefaultInputFile file = new DefaultInputFile(PROJECT_KEY, "src/foo.java")
+ .setLines(3)
+ .setOriginalLineOffsets(new long[] {0, 4, 7});
+
+ SyntaxHighlightingData highlighting = new SyntaxHighlightingDataBuilder()
+ .registerHighlightingRule(0, 3, TypeOfText.ANNOTATION)
+ .registerHighlightingRule(4, 9, TypeOfText.COMMENT)
+ .registerHighlightingRule(10, 16, TypeOfText.CONSTANT)
+ .build();
+
+ String[] highlightingPerLine = sourcePersister.computeHighlightingPerLine(file, highlighting);
+
+ assertThat(highlightingPerLine).containsOnly("0,3,a", "0,3,cd", "0,2,cd;3,9,c");
+ }
+
+ @Test
+ public void testConversionOfHighlightingNestedRules() {
+ DefaultInputFile file = new DefaultInputFile(PROJECT_KEY, "src/foo.java")
+ .setLines(3)
+ .setOriginalLineOffsets(new long[] {0, 4, 7});
+
+ SyntaxHighlightingData highlighting = new SyntaxHighlightingDataBuilder()
+ .registerHighlightingRule(0, 3, TypeOfText.ANNOTATION)
+ .registerHighlightingRule(4, 6, TypeOfText.COMMENT)
+ .registerHighlightingRule(7, 16, TypeOfText.CONSTANT)
+ .registerHighlightingRule(8, 15, TypeOfText.KEYWORD)
+ .build();
+
+ String[] highlightingPerLine = sourcePersister.computeHighlightingPerLine(file, highlighting);
+
+ assertThat(highlightingPerLine).containsOnly("0,3,a", "0,2,cd", "0,9,c;1,8,k");
+ }
+
+ @Test
+ public void testConversionOfHighlightingNestedRulesMultiLine() {
+ DefaultInputFile file = new DefaultInputFile(PROJECT_KEY, "src/foo.java")
+ .setLines(3)
+ .setOriginalLineOffsets(new long[] {0, 4, 7});
+
+ SyntaxHighlightingData highlighting = new SyntaxHighlightingDataBuilder()
+ .registerHighlightingRule(0, 3, TypeOfText.ANNOTATION)
+ .registerHighlightingRule(4, 6, TypeOfText.COMMENT)
+ .registerHighlightingRule(4, 16, TypeOfText.CONSTANT)
+ .registerHighlightingRule(8, 15, TypeOfText.KEYWORD)
+ .build();
+
+ String[] highlightingPerLine = sourcePersister.computeHighlightingPerLine(file, highlighting);
+
+ assertThat(highlightingPerLine).containsOnly("0,3,a", "0,3,c;0,2,cd", "0,9,c;1,8,k");
+ }
+
private void mockResourceCache(String relativePathEmpty, String projectKey, String uuid) {
File sonarFile = File.create(relativePathEmpty);
sonarFile.setUuid(uuid);