aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/sonar-core-plugin
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-10-29 18:51:26 +0100
committerJulien HENRY <julien.henry@sonarsource.com>2014-10-29 18:52:19 +0100
commitbbac6378c0ae04b5c2906858c4799989276883e6 (patch)
tree4d39e064ed6657a6bf057a75cffc39b0dff86234 /plugins/sonar-core-plugin
parentdb97e2170eca7b864b93063a62f1ead81d77a8df (diff)
downloadsonarqube-bbac6378c0ae04b5c2906858c4799989276883e6.tar.gz
sonarqube-bbac6378c0ae04b5c2906858c4799989276883e6.zip
SONAR-5375 Optimize issue tracking in case we have many issues of the same rule and on the same file
Diffstat (limited to 'plugins/sonar-core-plugin')
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java36
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingResult.java63
2 files changed, 61 insertions, 38 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java
index 876112646d9..d5dbcccc83f 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java
@@ -20,8 +20,6 @@
package org.sonar.plugins.core.issue;
-import org.sonar.plugins.core.issue.tracking.SourceChecksum;
-
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import com.google.common.collect.LinkedHashMultimap;
@@ -37,6 +35,7 @@ import org.sonar.plugins.core.issue.tracking.HashedSequenceComparator;
import org.sonar.plugins.core.issue.tracking.IssueTrackingBlocksRecognizer;
import org.sonar.plugins.core.issue.tracking.RollingHashSequence;
import org.sonar.plugins.core.issue.tracking.RollingHashSequenceComparator;
+import org.sonar.plugins.core.issue.tracking.SourceChecksum;
import org.sonar.plugins.core.issue.tracking.StringText;
import org.sonar.plugins.core.issue.tracking.StringTextComparator;
@@ -67,7 +66,6 @@ public class IssueTracking implements BatchExtension {
}
}
-
@VisibleForTesting
void mapIssues(Collection<DefaultIssue> newIssues, @Nullable Collection<IssueDto> lastIssues, SourceHashHolder sourceHashHolder, IssueTrackingResult result) {
boolean hasLastScan = false;
@@ -93,7 +91,7 @@ public class IssueTracking implements BatchExtension {
// Match the key of the issue. (For manual issues)
for (DefaultIssue newIssue : newIssues) {
- mapIssue(newIssue, findLastIssueWithSameKey(newIssue, result.unmatchedForRule(newIssue.ruleKey())), result);
+ mapIssue(newIssue, result.unmatchedByKeyForRule(newIssue.ruleKey()).get(newIssue.key()), result);
}
// Try first to match issues on same rule with same line and with same checksum (but not necessarily with same message)
@@ -101,7 +99,7 @@ public class IssueTracking implements BatchExtension {
if (isNotAlreadyMapped(newIssue, result)) {
mapIssue(
newIssue,
- findLastIssueWithSameLineAndChecksum(newIssue, result.unmatchedForRule(newIssue.ruleKey())),
+ findLastIssueWithSameLineAndChecksum(newIssue, result),
result);
}
}
@@ -176,7 +174,7 @@ public class IssueTracking implements BatchExtension {
if (isNotAlreadyMapped(newIssue, result)) {
mapIssue(
newIssue,
- findLastIssueWithSameChecksumAndMessage(newIssue, result.unmatchedForRule(newIssue.ruleKey())),
+ findLastIssueWithSameChecksumAndMessage(newIssue, result.unmatchedByKeyForRule(newIssue.ruleKey()).values()),
result);
}
}
@@ -186,7 +184,7 @@ public class IssueTracking implements BatchExtension {
if (isNotAlreadyMapped(newIssue, result)) {
mapIssue(
newIssue,
- findLastIssueWithSameLineAndMessage(newIssue, result.unmatchedForRule(newIssue.ruleKey())),
+ findLastIssueWithSameLineAndMessage(newIssue, result.unmatchedByKeyForRule(newIssue.ruleKey()).values()),
result);
}
}
@@ -197,7 +195,7 @@ public class IssueTracking implements BatchExtension {
if (isNotAlreadyMapped(newIssue, result)) {
mapIssue(
newIssue,
- findLastIssueWithSameChecksum(newIssue, result.unmatchedForRule(newIssue.ruleKey())),
+ findLastIssueWithSameChecksum(newIssue, result.unmatchedByKeyForRule(newIssue.ruleKey()).values()),
result);
}
}
@@ -263,20 +261,10 @@ public class IssueTracking implements BatchExtension {
return null;
}
- private IssueDto findLastIssueWithSameLineAndChecksum(DefaultIssue newIssue, Collection<IssueDto> lastIssues) {
- for (IssueDto pastIssue : lastIssues) {
- if (isSameLine(newIssue, pastIssue) && isSameChecksum(newIssue, pastIssue)) {
- return pastIssue;
- }
- }
- return null;
- }
-
- private IssueDto findLastIssueWithSameKey(DefaultIssue newIssue, Collection<IssueDto> lastIssues) {
- for (IssueDto pastIssue : lastIssues) {
- if (isSameKey(newIssue, pastIssue)) {
- return pastIssue;
- }
+ private IssueDto findLastIssueWithSameLineAndChecksum(DefaultIssue newIssue, IssueTrackingResult result) {
+ Collection<IssueDto> sameRuleAndSameLineAndSameChecksum = result.unmatchedForRuleAndForLineAndForChecksum(newIssue.ruleKey(), newIssue.line(), newIssue.checksum());
+ if (!sameRuleAndSameLineAndSameChecksum.isEmpty()) {
+ return sameRuleAndSameLineAndSameChecksum.iterator().next();
}
return null;
}
@@ -301,10 +289,6 @@ public class IssueTracking implements BatchExtension {
return Objects.equal(newIssue.message(), pastIssue.getMessage());
}
- private boolean isSameKey(DefaultIssue newIssue, IssueDto pastIssue) {
- return Objects.equal(newIssue.key(), pastIssue.getKee());
- }
-
private void mapIssue(DefaultIssue issue, @Nullable IssueDto ref, IssueTrackingResult result) {
if (ref != null) {
result.setMatch(issue, ref);
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingResult.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingResult.java
index a3f84600a89..147d89ef01c 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingResult.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingResult.java
@@ -19,29 +19,51 @@
*/
package org.sonar.plugins.core.issue;
-import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.HashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
+import org.apache.commons.lang.StringUtils;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.rule.RuleKey;
import org.sonar.core.issue.db.IssueDto;
+import javax.annotation.Nullable;
+
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
-import java.util.Set;
class IssueTrackingResult {
- private final Set<IssueDto> unmatched = Sets.newHashSet();
- private final Multimap<RuleKey, IssueDto> unmatchedByRule = LinkedHashMultimap.create();
+ private final Map<String, IssueDto> unmatchedByKey = new HashMap<String, IssueDto>();
+ private final Map<RuleKey, Map<String, IssueDto>> unmatchedByRuleAndKey = new HashMap<RuleKey, Map<String, IssueDto>>();
+ private final Map<RuleKey, Map<Integer, Multimap<String, IssueDto>>> unmatchedByRuleAndLineAndChecksum =
+ new HashMap<RuleKey, Map<Integer, Multimap<String, IssueDto>>>();
private final Map<DefaultIssue, IssueDto> matched = Maps.newIdentityHashMap();
Collection<IssueDto> unmatched() {
- return unmatched;
+ return unmatchedByKey.values();
+ }
+
+ Map<String, IssueDto> unmatchedByKeyForRule(RuleKey ruleKey) {
+ return unmatchedByRuleAndKey.containsKey(ruleKey) ? unmatchedByRuleAndKey.get(ruleKey) : Collections.<String, IssueDto>emptyMap();
}
- Collection<IssueDto> unmatchedForRule(RuleKey ruleKey) {
- return unmatchedByRule.get(ruleKey);
+ Collection<IssueDto> unmatchedForRuleAndForLineAndForChecksum(RuleKey ruleKey, @Nullable Integer line, @Nullable String checksum) {
+ if (!unmatchedByRuleAndLineAndChecksum.containsKey(ruleKey)) {
+ return Collections.emptyList();
+ }
+ Map<Integer, Multimap<String, IssueDto>> unmatchedForRule = unmatchedByRuleAndLineAndChecksum.get(ruleKey);
+ Integer lineNotNull = line != null ? line : 0;
+ if (!unmatchedForRule.containsKey(lineNotNull)) {
+ return Collections.emptyList();
+ }
+ Multimap<String, IssueDto> unmatchedForRuleAndLine = unmatchedForRule.get(lineNotNull);
+ String checksumNotNull = StringUtils.defaultString(checksum, "");
+ if (!unmatchedForRuleAndLine.containsKey(checksumNotNull)) {
+ return Collections.emptyList();
+ }
+ return unmatchedForRuleAndLine.get(checksumNotNull);
}
Collection<DefaultIssue> matched() {
@@ -57,13 +79,30 @@ class IssueTrackingResult {
}
void addUnmatched(IssueDto i) {
- unmatched.add(i);
- unmatchedByRule.put(RuleKey.of(i.getRuleRepo(), i.getRule()), i);
+ unmatchedByKey.put(i.getKee(), i);
+ RuleKey ruleKey = RuleKey.of(i.getRuleRepo(), i.getRule());
+ if (!unmatchedByRuleAndKey.containsKey(ruleKey)) {
+ unmatchedByRuleAndKey.put(ruleKey, new HashMap<String, IssueDto>());
+ unmatchedByRuleAndLineAndChecksum.put(ruleKey, new HashMap<Integer, Multimap<String, IssueDto>>());
+ }
+ unmatchedByRuleAndKey.get(ruleKey).put(i.getKee(), i);
+ Map<Integer, Multimap<String, IssueDto>> unmatchedForRule = unmatchedByRuleAndLineAndChecksum.get(ruleKey);
+ Integer lineNotNull = i.getLine() != null ? i.getLine() : 0;
+ if (!unmatchedForRule.containsKey(lineNotNull)) {
+ unmatchedForRule.put(lineNotNull, HashMultimap.<String, IssueDto>create());
+ }
+ Multimap<String, IssueDto> unmatchedForRuleAndLine = unmatchedForRule.get(lineNotNull);
+ String checksumNotNull = StringUtils.defaultString(i.getChecksum(), "");
+ unmatchedForRuleAndLine.put(checksumNotNull, i);
}
void setMatch(DefaultIssue issue, IssueDto matching) {
matched.put(issue, matching);
- unmatchedByRule.remove(RuleKey.of(matching.getRuleRepo(), matching.getRule()), matching);
- unmatched.remove(matching);
+ RuleKey ruleKey = RuleKey.of(matching.getRuleRepo(), matching.getRule());
+ unmatchedByRuleAndKey.get(ruleKey).remove(matching.getKee());
+ unmatchedByKey.remove(matching.getKee());
+ Integer lineNotNull = matching.getLine() != null ? matching.getLine() : 0;
+ String checksumNotNull = StringUtils.defaultString(matching.getChecksum(), "");
+ unmatchedByRuleAndLineAndChecksum.get(ruleKey).get(lineNotNull).get(checksumNotNull).remove(matching);
}
}