From: Duarte Meneses Date: Mon, 9 Apr 2018 15:46:48 +0000 (+0200) Subject: SONAR-10544 Load external rules X-Git-Tag: 7.5~1328 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=e75191dffd58fe63583c5da60eca9b5febf823b0;p=sonarqube.git SONAR-10544 Load external rules --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/NewExternalRule.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/NewExternalRule.java new file mode 100644 index 00000000000..a74632d02ff --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/NewExternalRule.java @@ -0,0 +1,168 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.task.projectanalysis.issue; + +import java.util.Collections; +import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.concurrent.Immutable; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rules.RuleType; +import org.sonar.api.server.debt.DebtRemediationFunction; + +@Immutable +public class NewExternalRule implements Rule { + private final RuleKey key; + private final String name; + private final String descriptionUrl; + private final String severity; + private final RuleType type; + + private NewExternalRule(Builder builder) { + this.key = checkNotNull(builder.key, "key"); + this.name = checkNotEmpty(builder.name, "name"); + this.descriptionUrl = builder.descriptionUrl; + this.severity = checkNotEmpty(builder.severity, "severity"); + this.type = checkNotNull(builder.type, "type"); + } + + private static String checkNotEmpty(String str, String name) { + if (StringUtils.isEmpty(str)) { + throw new IllegalStateException("'" + name + "' not expected to be empty for an external rule"); + } + return str; + } + + private static T checkNotNull(T obj, String name) { + if (obj == null) { + throw new IllegalStateException("'" + name + "' not expected to be null for an external rule"); + } + return obj; + } + + @CheckForNull + public String getDescriptionUrl() { + return descriptionUrl; + } + + public String getSeverity() { + return severity; + } + + @Override + public int getId() { + return 0; + } + + @Override + public RuleKey getKey() { + return key; + } + + @Override + public String getName() { + return name; + } + + @Override + public RuleStatus getStatus() { + return RuleStatus.defaultStatus(); + } + + @Override + public RuleType getType() { + return type; + } + + @Override + public boolean isExternal() { + return true; + } + + @Override + public Set getTags() { + return Collections.emptySet(); + } + + @Override + public DebtRemediationFunction getRemediationFunction() { + return null; + } + + @Override + public String getPluginKey() { + return null; + } + + public static class Builder { + private RuleKey key; + private String name; + private String descriptionUrl; + private String severity; + private RuleType type; + + public Builder setKey(RuleKey key) { + this.key = key; + return this; + } + + public Builder setName(String name) { + this.name = StringUtils.trimToNull(name); + return this; + } + + public Builder setDescriptionUrl(String descriptionUrl) { + this.descriptionUrl = StringUtils.trimToNull(descriptionUrl); + return this; + } + + public Builder setSeverity(String severity) { + this.severity = StringUtils.trimToNull(severity); + return this; + } + + public Builder setType(RuleType type) { + this.type = type; + return this; + } + + public String name() { + return name; + } + + public String descriptionUrl() { + return descriptionUrl; + } + + public String severity() { + return severity; + } + + public RuleType type() { + return type; + } + + public NewExternalRule build() { + return new NewExternalRule(this); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/Rule.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/Rule.java index 00cf9755c34..a3a56a743c0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/Rule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/Rule.java @@ -37,6 +37,8 @@ public interface Rule { RuleStatus getStatus(); RuleType getType(); + + boolean isExternal(); /** * Get all tags, whatever system or user tags. diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleImpl.java index 097e15301b1..4762cef0629 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleImpl.java @@ -44,6 +44,7 @@ public class RuleImpl implements Rule { private final DebtRemediationFunction remediationFunction; private final RuleType type; private final String pluginKey; + private final boolean external; public RuleImpl(RuleDto dto) { this.id = dto.getId(); @@ -54,6 +55,8 @@ public class RuleImpl implements Rule { this.remediationFunction = effectiveRemediationFunction(dto); this.type = RuleType.valueOf(dto.getType()); this.pluginKey = dto.getPluginKey(); + // TODO + this.external = false; } @Override @@ -138,4 +141,9 @@ public class RuleImpl implements Rule { } return null; } + + @Override + public boolean isExternal() { + return external; + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepository.java index 8bf1e494d19..347638cddc4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepository.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepository.java @@ -20,6 +20,7 @@ package org.sonar.server.computation.task.projectanalysis.issue; import java.util.Optional; +import java.util.function.Supplier; import org.sonar.api.rule.RuleKey; /** @@ -44,4 +45,6 @@ public interface RuleRepository { Optional findByKey(RuleKey key); Optional findById(int id); + + void insertNewExternalRuleIfAbsent(RuleKey ruleKey, Supplier ruleSupplier); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImpl.java index 347cea214d0..e7f3cd61d80 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImpl.java @@ -21,8 +21,10 @@ package org.sonar.server.computation.task.projectanalysis.issue; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Multimap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; +import java.util.function.Supplier; import javax.annotation.CheckForNull; import org.sonar.api.rule.RuleKey; import org.sonar.core.util.stream.MoreCollectors; @@ -41,6 +43,8 @@ public class RuleRepositoryImpl implements RuleRepository { private Map rulesByKey; @CheckForNull private Map rulesById; + @CheckForNull + private Map newExternalRulesByKey; private final DbClient dbClient; private final AnalysisMetadataHolder analysisMetadataHolder; @@ -50,6 +54,12 @@ public class RuleRepositoryImpl implements RuleRepository { this.analysisMetadataHolder = analysisMetadataHolder; } + public void insertNewExternalRuleIfAbsent(RuleKey ruleKey, Supplier ruleSupplier) { + if (!rulesByKey.containsKey(ruleKey)) { + newExternalRulesByKey.computeIfAbsent(ruleKey, s -> ruleSupplier.get()); + } + } + @Override public Rule getByKey(RuleKey key) { verifyKeyArgument(key); @@ -112,6 +122,7 @@ public class RuleRepositoryImpl implements RuleRepository { } this.rulesByKey = rulesByKeyBuilder.build(); this.rulesById = rulesByIdBuilder.build(); + this.newExternalRulesByKey = new LinkedHashMap<>(); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleTagsCopier.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleTagsCopier.java index 78ffaf7654f..2f6d220b7a0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleTagsCopier.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleTagsCopier.java @@ -37,7 +37,9 @@ public class RuleTagsCopier extends IssueVisitor { if (issue.isNew()) { // analyzer can provide some tags. They must be merged with rule tags Rule rule = ruleRepository.getByKey(issue.ruleKey()); - issue.setTags(union(issue.tags(), rule.getTags())); + if (!rule.isExternal()) { + issue.setTags(union(issue.tags(), rule.getTags())); + } } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleTypeCopier.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleTypeCopier.java index d58935099d5..58234a9031a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleTypeCopier.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleTypeCopier.java @@ -34,7 +34,9 @@ public class RuleTypeCopier extends IssueVisitor { public void onIssue(Component component, DefaultIssue issue) { if (issue.type() == null) { Rule rule = ruleRepository.getByKey(issue.ruleKey()); - issue.setType(rule.getType()); + if (!rule.isExternal()) { + issue.setType(rule.getType()); + } } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java index bd2e6f6d396..0bc49a026d6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java @@ -56,14 +56,16 @@ public class TrackerRawInputFactory { private final SourceLinesRepository sourceLinesRepository; private final CommonRuleEngine commonRuleEngine; private final IssueFilter issueFilter; + private final RuleRepository ruleRepository; public TrackerRawInputFactory(TreeRootHolder treeRootHolder, BatchReportReader reportReader, - SourceLinesRepository sourceLinesRepository, CommonRuleEngine commonRuleEngine, IssueFilter issueFilter) { + SourceLinesRepository sourceLinesRepository, CommonRuleEngine commonRuleEngine, IssueFilter issueFilter, RuleRepository ruleRepository) { this.treeRootHolder = treeRootHolder; this.reportReader = reportReader; this.sourceLinesRepository = sourceLinesRepository; this.commonRuleEngine = commonRuleEngine; this.issueFilter = issueFilter; + this.ruleRepository = ruleRepository; } public Input create(Component component) { @@ -120,8 +122,7 @@ public class TrackerRawInputFactory { // as late as possible while (reportIssues.hasNext()) { ScannerReport.ExternalIssue reportExternalIssue = reportIssues.next(); - DefaultIssue issue = toIssue(getLineHashSequence(), reportExternalIssue); - result.add(issue); + result.add(toExternalIssue(getLineHashSequence(), reportExternalIssue)); } } @@ -171,10 +172,11 @@ public class TrackerRawInputFactory { return issue; } - private DefaultIssue toIssue(LineHashSequence lineHashSeq, ScannerReport.ExternalIssue reportIssue) { + private DefaultIssue toExternalIssue(LineHashSequence lineHashSeq, ScannerReport.ExternalIssue reportIssue) { DefaultIssue issue = new DefaultIssue(); init(issue); - issue.setRuleKey(RuleKey.of(reportIssue.getRuleRepository(), reportIssue.getRuleKey())); + + issue.setRuleKey(RuleKey.of(RuleKey.EXTERNAL_RULE_REPO_PREFIX + reportIssue.getRuleRepository(), reportIssue.getRuleKey())); if (reportIssue.hasTextRange()) { int startLine = reportIssue.getTextRange().getStartLine(); issue.setLine(startLine); @@ -206,10 +208,25 @@ public class TrackerRawInputFactory { } issue.setLocations(dbLocationsBuilder.build()); issue.setType(toRuleType(reportIssue.getType())); - issue.setDescriptionUrl(StringUtils.stripToNull(reportIssue.getDescriptionUrl())); + + ruleRepository.insertNewExternalRuleIfAbsent(issue.getRuleKey(), () -> toExternalRule(reportIssue)); return issue; } + private NewExternalRule toExternalRule(ScannerReport.ExternalIssue reportIssue) { + NewExternalRule.Builder builder = new NewExternalRule.Builder() + .setDescriptionUrl(StringUtils.stripToNull(reportIssue.getDescriptionUrl())) + .setType(toRuleType(reportIssue.getType())) + .setKey(RuleKey.of(RuleKey.EXTERNAL_RULE_REPO_PREFIX + reportIssue.getRuleRepository(), reportIssue.getRuleKey())) + .setPluginKey(reportIssue.getRuleRepository()) + .setName(reportIssue.getRuleName()); + + if (reportIssue.getSeverity() != Severity.UNSET_SEVERITY) { + builder.setSeverity(reportIssue.getSeverity().name()); + } + return builder.build(); + } + private RuleType toRuleType(IssueType type) { switch (type) { case BUG: diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadQualityProfilesStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadQualityProfilesStep.java index f0ab906b526..4037cbb763c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadQualityProfilesStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadQualityProfilesStep.java @@ -54,7 +54,7 @@ public class LoadQualityProfilesStep implements ComputationStep { while (batchActiveRules.hasNext()) { ScannerReport.ActiveRule scannerReportActiveRule = batchActiveRules.next(); Optional rule = ruleRepository.findByKey(RuleKey.of(scannerReportActiveRule.getRuleRepository(), scannerReportActiveRule.getRuleKey())); - if (rule.isPresent() && rule.get().getStatus() != RuleStatus.REMOVED) { + if (rule.isPresent() && rule.get().getStatus() != RuleStatus.REMOVED && !rule.get().isExternal()) { ActiveRule activeRule = convert(scannerReportActiveRule, rule.get()); activeRules.add(activeRule); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DumbRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DumbRule.java index dc5f9c92796..e6066c8c984 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DumbRule.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DumbRule.java @@ -38,6 +38,7 @@ public class DumbRule implements Rule { private Set tags = new HashSet<>(); private DebtRemediationFunction function; private String pluginKey; + private boolean isExternal; public DumbRule(RuleKey key) { this.key = key; @@ -84,6 +85,11 @@ public class DumbRule implements Rule { return pluginKey; } + @Override + public boolean isExternal() { + return isExternal; + } + public DumbRule setId(Integer id) { this.id = id; return this; @@ -119,4 +125,9 @@ public class DumbRule implements Rule { return this; } + public DumbRule setIsExtenral(boolean isExternal) { + this.isExternal = isExternal; + return this; + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java index 629aad4894b..807cc1176b4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java @@ -27,8 +27,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.sonar.api.issue.Issue; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; @@ -104,23 +102,17 @@ public class IntegrateIssuesVisitorTest { public RuleRepositoryRule ruleRepositoryRule = new RuleRepositoryRule(); @Rule public SourceLinesRepositoryRule fileSourceRepository = new SourceLinesRepositoryRule(); + @Rule + public RuleRepositoryRule ruleRepository = new RuleRepositoryRule(); - @Mock - private AnalysisMetadataHolder analysisMetadataHolder; - @Mock - private IssueFilter issueFilter; - @Mock - private MovedFilesRepository movedFilesRepository; - @Mock - private IssueLifecycle issueLifecycle; - @Mock - private IssueVisitor issueVisitor; - @Mock - private MergeBranchComponentUuids mergeBranchComponentsUuids; - @Mock - private ShortBranchIssueMerger issueStatusCopier; - @Mock - private MergeBranchComponentUuids mergeBranchComponentUuids; + private AnalysisMetadataHolder analysisMetadataHolder = mock(AnalysisMetadataHolder.class); + private IssueFilter issueFilter = mock(IssueFilter.class); + private MovedFilesRepository movedFilesRepository = mock(MovedFilesRepository.class); + private IssueLifecycle issueLifecycle = mock(IssueLifecycle.class); + private IssueVisitor issueVisitor = mock(IssueVisitor.class); + private MergeBranchComponentUuids mergeBranchComponentsUuids = mock(MergeBranchComponentUuids.class); + private ShortBranchIssueMerger issueStatusCopier = mock(ShortBranchIssueMerger.class); + private MergeBranchComponentUuids mergeBranchComponentUuids = mock(MergeBranchComponentUuids.class); ArgumentCaptor defaultIssueCaptor; @@ -135,13 +127,13 @@ public class IntegrateIssuesVisitorTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); IssueVisitors issueVisitors = new IssueVisitors(new IssueVisitor[] {issueVisitor}); defaultIssueCaptor = ArgumentCaptor.forClass(DefaultIssue.class); when(movedFilesRepository.getOriginalFile(any(Component.class))).thenReturn(Optional.absent()); - TrackerRawInputFactory rawInputFactory = new TrackerRawInputFactory(treeRootHolder, reportReader, fileSourceRepository, new CommonRuleEngineImpl(), issueFilter); + TrackerRawInputFactory rawInputFactory = new TrackerRawInputFactory(treeRootHolder, reportReader, fileSourceRepository, new CommonRuleEngineImpl(), + issueFilter, ruleRepository); TrackerBaseInputFactory baseInputFactory = new TrackerBaseInputFactory(issuesLoader, dbTester.getDbClient(), movedFilesRepository); TrackerMergeBranchInputFactory mergeInputFactory = new TrackerMergeBranchInputFactory(issuesLoader, mergeBranchComponentsUuids, dbTester.getDbClient()); tracker = new TrackerExecution(baseInputFactory, rawInputFactory, new Tracker<>()); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/NewExternalRuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/NewExternalRuleTest.java new file mode 100644 index 00000000000..4b5f1944350 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/NewExternalRuleTest.java @@ -0,0 +1,83 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.task.projectanalysis.issue; + +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rules.RuleType; + +import static org.assertj.core.api.Assertions.assertThat; + +public class NewExternalRuleTest { + @org.junit.Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void should_build_new_external_rule() { + NewExternalRule.Builder builder = new NewExternalRule.Builder() + .setDescriptionUrl("url") + .setKey(RuleKey.of("repo", "rule")) + .setName("name") + .setSeverity("MAJOR") + .setType(RuleType.BUG); + + assertThat(builder.descriptionUrl()).isEqualTo("url"); + assertThat(builder.name()).isEqualTo("name"); + assertThat(builder.severity()).isEqualTo("MAJOR"); + assertThat(builder.type()).isEqualTo(RuleType.BUG); + assertThat(builder.descriptionUrl()).isEqualTo("url"); + + NewExternalRule rule = builder.build(); + + assertThat(rule.getDescriptionUrl()).isEqualTo("url"); + assertThat(rule.getName()).isEqualTo("name"); + assertThat(rule.getPluginKey()).isNull(); + assertThat(rule.getSeverity()).isEqualTo("MAJOR"); + assertThat(rule.getType()).isEqualTo(RuleType.BUG); + assertThat(rule.getDescriptionUrl()).isEqualTo("url"); + } + + @Test + public void fail_if_name_is_not_set() { + exception.expect(IllegalStateException.class); + exception.expectMessage("'name' not expected to be empty for an external rule"); + + new NewExternalRule.Builder() + .setDescriptionUrl("url") + .setKey(RuleKey.of("repo", "rule")) + .setSeverity("MAJOR") + .setType(RuleType.BUG) + .build(); + } + + @Test + public void fail_if_rule_key_is_not_set() { + exception.expect(IllegalStateException.class); + exception.expectMessage("'key' not expected to be null for an external rule"); + + new NewExternalRule.Builder() + .setDescriptionUrl("url") + .setName("name") + .setSeverity("MAJOR") + .setType(RuleType.BUG) + .build(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryRule.java index 52939ddb8f5..698954885aa 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryRule.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryRule.java @@ -22,6 +22,7 @@ package org.sonar.server.computation.task.projectanalysis.issue; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.function.Supplier; import org.junit.rules.ExternalResource; import org.sonar.api.rule.RuleKey; @@ -32,6 +33,7 @@ public class RuleRepositoryRule extends ExternalResource implements RuleReposito private final Map rulesByKey = new HashMap<>(); private final Map rulesById = new HashMap<>(); + private final Map newExternalRulesById = new HashMap<>(); @Override protected void after() { @@ -77,4 +79,9 @@ public class RuleRepositoryRule extends ExternalResource implements RuleReposito return this; } + @Override + public void insertNewExternalRuleIfAbsent(RuleKey ruleKey, Supplier ruleSupplier) { + newExternalRulesById.computeIfAbsent(ruleKey, k -> ruleSupplier.get()); + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactoryTest.java index d6cd5b1c129..4bfe7bfd937 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactoryTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactoryTest.java @@ -62,12 +62,13 @@ public class TrackerRawInputFactoryTest { @Rule public SourceLinesRepositoryRule fileSourceRepository = new SourceLinesRepositoryRule(); + + @Rule + public RuleRepositoryRule ruleRepository = new RuleRepositoryRule(); CommonRuleEngine commonRuleEngine = mock(CommonRuleEngine.class); - IssueFilter issueFilter = mock(IssueFilter.class); - - TrackerRawInputFactory underTest = new TrackerRawInputFactory(treeRootHolder, reportReader, fileSourceRepository, commonRuleEngine, issueFilter); + TrackerRawInputFactory underTest = new TrackerRawInputFactory(treeRootHolder, reportReader, fileSourceRepository, commonRuleEngine, issueFilter, ruleRepository); @Test public void load_source_hash_sequences() {