diff options
Diffstat (limited to 'sonar-batch')
7 files changed, 49 insertions, 17 deletions
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 186e37edaa6..342c3503fb6 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 @@ -58,7 +58,9 @@ import javax.annotation.Nullable; import java.io.IOException; import java.io.StringWriter; +import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -330,7 +332,15 @@ public class SourcePersister implements ScanPersister { StringBuilder[] symbolRefsPerLine = new StringBuilder[file.lines()]; long[] originalLineOffsets = file.originalLineOffsets(); int symbolId = 1; - for (Symbol symbol : symbolRefs.referencesBySymbol().keySet()) { + List<Symbol> symbols = new ArrayList<Symbol>(symbolRefs.referencesBySymbol().keySet()); + // Sort symbols to avoid false variation that would lead to an unnecessary update + Collections.sort(symbols, new Comparator<Symbol>() { + @Override + public int compare(Symbol o1, Symbol o2) { + return o1.getDeclarationStartOffset() - o2.getDeclarationStartOffset(); + } + }); + for (Symbol symbol : symbols) { int declarationStartOffset = symbol.getDeclarationStartOffset(); int declarationEndOffset = symbol.getDeclarationEndOffset(); int length = declarationEndOffset - declarationStartOffset; diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java index 8499776bfb7..2886cfbc28c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java +++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java @@ -80,6 +80,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; /** * Main utility class for writing batch medium tests. @@ -406,7 +407,7 @@ public class BatchMediumTester { * @param symbolEndOffset 0-based end offset for the symbol in file */ @CheckForNull - public List<Integer> symbolReferencesFor(InputFile file, int symbolStartOffset, int symbolEndOffset) { + public Set<Integer> symbolReferencesFor(InputFile file, int symbolStartOffset, int symbolEndOffset) { SymbolData data = symbolTablePerFile.get(file); if (data == null) { return null; diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolTable.java b/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolTable.java index 8aafb847386..b4ce0c15878 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolTable.java +++ b/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolTable.java @@ -28,16 +28,18 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; public class DefaultSymbolTable implements Symbolizable.SymbolTable { - private Map<Symbol, List<Integer>> referencesBySymbol; + private Map<Symbol, Set<Integer>> referencesBySymbol; - private DefaultSymbolTable(Map<Symbol, List<Integer>> referencesBySymbol) { + private DefaultSymbolTable(Map<Symbol, Set<Integer>> referencesBySymbol) { this.referencesBySymbol = referencesBySymbol; } - public Map<Symbol, List<Integer>> getReferencesBySymbol() { + public Map<Symbol, Set<Integer>> getReferencesBySymbol() { return referencesBySymbol; } @@ -57,7 +59,7 @@ public class DefaultSymbolTable implements Symbolizable.SymbolTable { public static class Builder implements Symbolizable.SymbolTableBuilder { - private final Map<Symbol, List<Integer>> referencesBySymbol = new LinkedHashMap<Symbol, List<Integer>>(); + private final Map<Symbol, Set<Integer>> referencesBySymbol = new LinkedHashMap<Symbol, Set<Integer>>(); private final String componentKey; public Builder(String componentKey) { @@ -67,7 +69,7 @@ public class DefaultSymbolTable implements Symbolizable.SymbolTable { @Override public Symbol newSymbol(int fromOffset, int toOffset) { Symbol symbol = new DefaultSymbol(fromOffset, toOffset); - referencesBySymbol.put(symbol, new ArrayList<Integer>()); + referencesBySymbol.put(symbol, new TreeSet<Integer>()); return symbol; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/symbol/DefaultSymbolTableBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/symbol/DefaultSymbolTableBuilder.java index a6e8c8c0aaf..72d4c050eb4 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/symbol/DefaultSymbolTableBuilder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/symbol/DefaultSymbolTableBuilder.java @@ -27,17 +27,17 @@ import org.sonar.batch.index.ComponentDataCache; import org.sonar.core.source.SnapshotDataTypes; import java.io.Serializable; -import java.util.ArrayList; import java.util.Comparator; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; public class DefaultSymbolTableBuilder implements SymbolTableBuilder { private final String componentKey; private final ComponentDataCache cache; - private final Map<org.sonar.api.source.Symbol, List<Integer>> referencesBySymbol = new LinkedHashMap<org.sonar.api.source.Symbol, List<Integer>>(); + private final Map<org.sonar.api.source.Symbol, Set<Integer>> referencesBySymbol = new LinkedHashMap<org.sonar.api.source.Symbol, Set<Integer>>(); public DefaultSymbolTableBuilder(String componentKey, ComponentDataCache cache) { this.componentKey = componentKey; @@ -47,7 +47,7 @@ public class DefaultSymbolTableBuilder implements SymbolTableBuilder { @Override public Symbol newSymbol(int fromOffset, int toOffset) { org.sonar.api.source.Symbol symbol = new DefaultSymbol(fromOffset, toOffset); - referencesBySymbol.put(symbol, new ArrayList<Integer>()); + referencesBySymbol.put(symbol, new TreeSet<Integer>()); return symbol; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/symbol/SymbolData.java b/sonar-batch/src/main/java/org/sonar/batch/symbol/SymbolData.java index 0f55e194e8b..baf897c6d1b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/symbol/SymbolData.java +++ b/sonar-batch/src/main/java/org/sonar/batch/symbol/SymbolData.java @@ -24,21 +24,21 @@ import org.sonar.api.batch.sensor.symbol.Symbol; import org.sonar.batch.index.Data; import java.util.Collection; -import java.util.List; import java.util.Map; +import java.util.Set; public class SymbolData implements Data { public static final String FIELD_SEPARATOR = ","; public static final String SYMBOL_SEPARATOR = ";"; - private final Map<org.sonar.api.source.Symbol, List<Integer>> referencesBySymbol; + private final Map<org.sonar.api.source.Symbol, Set<Integer>> referencesBySymbol; - public SymbolData(Map<org.sonar.api.source.Symbol, List<Integer>> referencesBySymbol) { + public SymbolData(Map<org.sonar.api.source.Symbol, Set<Integer>> referencesBySymbol) { this.referencesBySymbol = referencesBySymbol; } - public Map<org.sonar.api.source.Symbol, List<Integer>> referencesBySymbol() { + public Map<org.sonar.api.source.Symbol, Set<Integer>> referencesBySymbol() { return referencesBySymbol; } 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 af2c5474d94..4b405cca96c 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 @@ -362,6 +362,25 @@ public class SourcePersisterTest extends AbstractDaoTestCase { assertThat(symbolsPerLine).containsOnly("1,2,1;0,2,2", "0,1,1;0,2,2", "4,5,1;0,2,2"); } + @Test + public void verifyDeclarationOrderOfSymbolHasNoImpact() { + DefaultInputFile file = new DefaultInputFile(PROJECT_KEY, "src/foo.java") + .setLines(3) + .setOriginalLineOffsets(new long[] {0, 4, 7}); + + DefaultSymbolTableBuilder symbolBuilder = new DefaultSymbolTableBuilder(PROJECT_KEY + ":" + "src/foo.java", null); + org.sonar.api.batch.sensor.symbol.Symbol s2 = symbolBuilder.newSymbol(4, 6); + symbolBuilder.newReference(s2, 7); + symbolBuilder.newReference(s2, 0); + org.sonar.api.batch.sensor.symbol.Symbol s1 = symbolBuilder.newSymbol(1, 2); + symbolBuilder.newReference(s1, 11); + symbolBuilder.newReference(s1, 4); + + String[] symbolsPerLine = sourcePersister.computeSymbolReferencesPerLine(file, symbolBuilder.build()); + + assertThat(symbolsPerLine).containsOnly("1,2,1;0,2,2", "0,1,1;0,2,2", "4,5,1;0,2,2"); + } + private void mockResourceCache(String relativePathEmpty, String projectKey, String uuid) { File sonarFile = File.create(relativePathEmpty); sonarFile.setUuid(uuid); diff --git a/sonar-batch/src/test/java/org/sonar/batch/symbol/DefaultSymbolTableBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/symbol/DefaultSymbolTableBuilderTest.java index aa8c67edc56..c68156c0a2d 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/symbol/DefaultSymbolTableBuilderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/symbol/DefaultSymbolTableBuilderTest.java @@ -30,8 +30,8 @@ import org.sonar.batch.index.ComponentDataCache; import org.sonar.core.source.SnapshotDataTypes; import java.util.ArrayList; -import java.util.List; import java.util.Map; +import java.util.Set; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.eq; @@ -58,7 +58,7 @@ public class DefaultSymbolTableBuilderTest { ArgumentCaptor<SymbolData> argCaptor = ArgumentCaptor.forClass(SymbolData.class); verify(componentDataCache).setData(eq("foo"), eq(SnapshotDataTypes.SYMBOL_HIGHLIGHTING), argCaptor.capture()); - Map<org.sonar.api.source.Symbol, List<Integer>> referencesBySymbol = argCaptor.getValue().referencesBySymbol(); + Map<org.sonar.api.source.Symbol, Set<Integer>> referencesBySymbol = argCaptor.getValue().referencesBySymbol(); assertThat(new ArrayList<Symbol>(referencesBySymbol.keySet())).containsExactly(firstSymbol, secondSymbol, thirdSymbol); assertThat(new ArrayList<Integer>(referencesBySymbol.get(firstSymbol))).containsExactly(32); |