diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2016-02-01 11:51:27 +0100 |
---|---|---|
committer | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2016-02-01 16:52:24 +0100 |
commit | ed7a0167e3bfd31549213426a3bc3a101e2f4a9e (patch) | |
tree | 5ca3586dc754bd3a23d05823ad7ffb395403c6b2 /server | |
parent | 84d4f441879de01734bb9041fc0cdfbd461386ee (diff) | |
download | sonarqube-ed7a0167e3bfd31549213426a3bc3a101e2f4a9e.tar.gz sonarqube-ed7a0167e3bfd31549213426a3bc3a101e2f4a9e.zip |
SONAR-7257 make SymbolsLineReader instantaneous
Diffstat (limited to 'server')
-rw-r--r-- | server/sonar-server/src/main/java/org/sonar/server/computation/source/SymbolsLineReader.java | 77 |
1 files changed, 40 insertions, 37 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/source/SymbolsLineReader.java b/server/sonar-server/src/main/java/org/sonar/server/computation/source/SymbolsLineReader.java index 71853f79bc4..8d519a863ab 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/source/SymbolsLineReader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/source/SymbolsLineReader.java @@ -19,17 +19,16 @@ */ package org.sonar.server.computation.source; +import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; -import java.io.Serializable; +import com.google.common.collect.SetMultimap; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.batch.protocol.output.BatchReport; @@ -46,20 +45,20 @@ public class SymbolsLineReader implements LineReader { private final Component file; private final RangeOffsetConverter rangeOffsetConverter; - private final List<BatchReport.Symbol> symbols; private final Map<BatchReport.Symbol, Integer> idsBySymbol; + private final SetMultimap<Integer, BatchReport.Symbol> symbolsPerLine; private boolean areSymbolsValid = true; - public SymbolsLineReader(Component file, Iterator<BatchReport.Symbol> symbols, RangeOffsetConverter rangeOffsetConverter) { + public SymbolsLineReader(Component file, Iterator<BatchReport.Symbol> symbolIterator, RangeOffsetConverter rangeOffsetConverter) { this.file = file; this.rangeOffsetConverter = rangeOffsetConverter; - this.symbols = Lists.newArrayList(symbols); - // Sort symbols to have deterministic results and avoid false variation that would lead to an unnecessary update of the source files - // data - Collections.sort(this.symbols, new SymbolsComparator()); + List<BatchReport.Symbol> symbols = Lists.newArrayList(symbolIterator); + // Sort symbols to have deterministic id generation + Collections.sort(symbols, SymbolsComparator.INSTANCE); - this.idsBySymbol = createIdsBySymbolMap(this.symbols); + this.idsBySymbol = createIdsBySymbolMap(symbols); + this.symbolsPerLine = buildSymbolsPerLine(symbols); } @Override @@ -77,19 +76,23 @@ public class SymbolsLineReader implements LineReader { private void processSymbols(DbFileSources.Line.Builder lineBuilder) { int line = lineBuilder.getLine(); - List<BatchReport.Symbol> lineSymbols = findSymbolsMatchingLine(line); + + List<BatchReport.Symbol> lineSymbols = new ArrayList<>(this.symbolsPerLine.get(line)); + // Sort symbols to have deterministic results and avoid false variation that would lead to an unnecessary update of the source files + // data + Collections.sort(lineSymbols, SymbolsComparator.INSTANCE); + + StringBuilder symbolString = new StringBuilder(); for (BatchReport.Symbol lineSymbol : lineSymbols) { int symbolId = idsBySymbol.get(lineSymbol); - StringBuilder symbolString = new StringBuilder(lineBuilder.getSymbols()); appendSymbol(symbolString, lineSymbol.getDeclaration(), line, symbolId, lineBuilder.getSource()); for (BatchReport.TextRange range : lineSymbol.getReferenceList()) { appendSymbol(symbolString, range, line, symbolId, lineBuilder.getSource()); } - - if (symbolString.length() > 0) { - lineBuilder.setSymbols(symbolString.toString()); - } + } + if (symbolString.length() > 0) { + lineBuilder.setSymbols(symbolString.toString()); } } @@ -107,31 +110,12 @@ public class SymbolsLineReader implements LineReader { } } - private List<BatchReport.Symbol> findSymbolsMatchingLine(int line) { - List<BatchReport.Symbol> lineSymbols = new ArrayList<>(); - Set<BatchReport.Symbol> symbolsIndex = new HashSet<>(); - for (BatchReport.Symbol symbol : symbols) { - if (matchLine(symbol.getDeclaration(), line) && !symbolsIndex.contains(symbol)) { - lineSymbols.add(symbol); - symbolsIndex.add(symbol); - } else { - for (BatchReport.TextRange range : symbol.getReferenceList()) { - if (matchLine(range, line) && !symbolsIndex.contains(symbol)) { - lineSymbols.add(symbol); - symbolsIndex.add(symbol); - } - } - } - } - return lineSymbols; - } - private static boolean matchLine(BatchReport.TextRange range, int line) { return range.getStartLine() <= line && range.getEndLine() >= line; } private static Map<BatchReport.Symbol, Integer> createIdsBySymbolMap(List<BatchReport.Symbol> symbols) { - Map<BatchReport.Symbol, Integer> map = new HashMap<>(); + Map<BatchReport.Symbol, Integer> map = new HashMap<>(symbols.size()); int symbolId = 1; for (BatchReport.Symbol symbol : symbols) { map.put(symbol, symbolId); @@ -140,7 +124,26 @@ public class SymbolsLineReader implements LineReader { return map; } - private static class SymbolsComparator implements Comparator<BatchReport.Symbol>, Serializable { + private static SetMultimap<Integer, BatchReport.Symbol> buildSymbolsPerLine(List<BatchReport.Symbol> symbols) { + SetMultimap<Integer, BatchReport.Symbol> res = HashMultimap.create(); + for (BatchReport.Symbol symbol : symbols) { + putForTextRange(res, symbol, symbol.getDeclaration()); + for (BatchReport.TextRange textRange : symbol.getReferenceList()) { + putForTextRange(res, symbol, textRange); + } + } + return res; + } + + private static void putForTextRange(SetMultimap<Integer, BatchReport.Symbol> res, BatchReport.Symbol symbol, BatchReport.TextRange declaration) { + for (int i = declaration.getStartLine(); i <= declaration.getEndLine(); i++) { + res.put(i, symbol); + } + } + + private enum SymbolsComparator implements Comparator<BatchReport.Symbol> { + INSTANCE; + @Override public int compare(BatchReport.Symbol o1, BatchReport.Symbol o2) { if (o1.getDeclaration().getStartLine() == o2.getDeclaration().getStartLine()) { |