aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2018-04-13 09:12:54 +0200
committerSonarTech <sonartech@sonarsource.com>2018-04-26 20:20:50 +0200
commit0672145e58ce28f8fb475bc53f095f16dfaeeb1d (patch)
tree3d520cdc9e39becccf9f6a33c1d1b7843aec11f6
parent0e3a5a4e118e66bf4d2d17a1a745859c4351225a (diff)
downloadsonarqube-0672145e58ce28f8fb475bc53f095f16dfaeeb1d.tar.gz
sonarqube-0672145e58ce28f8fb475bc53f095f16dfaeeb1d.zip
SONAR-10544 Fix tests handling of external rules
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeactivateRulesAction.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java20
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculatorTest.java40
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistExternalRulesStepTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistIssuesStepTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java10
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java1
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java3
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java2
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ModuleIssues.java2
16 files changed, 81 insertions, 41 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java
index 6b132a30187..8818dadff9b 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java
@@ -35,7 +35,7 @@ import org.sonar.server.user.UserSession;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_03;
import static org.sonar.server.qualityprofile.ws.BulkChangeWsResponse.writeResponse;
import static org.sonar.server.qualityprofile.ws.QProfileReference.fromKey;
-import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters;
+import static org.sonar.server.rule.ws.SearchAction.defineGenericRuleSearchParameters;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ACTIVATE_RULES;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_KEY;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_SEVERITY;
@@ -69,7 +69,7 @@ public class ActivateRulesAction implements QProfileWsAction {
.setSince("4.4")
.setHandler(this);
- defineRuleSearchParameters(activate);
+ defineGenericRuleSearchParameters(activate);
activate.createParam(PARAM_TARGET_KEY)
.setDescription("Quality Profile key on which the rule activation is done. To retrieve a quality profile key please see <code>api/qualityprofiles/search</code>")
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeactivateRulesAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeactivateRulesAction.java
index fd779c15d16..1a96919832e 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeactivateRulesAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeactivateRulesAction.java
@@ -33,7 +33,7 @@ import org.sonar.server.user.UserSession;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_04;
import static org.sonar.server.qualityprofile.ws.BulkChangeWsResponse.writeResponse;
-import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters;
+import static org.sonar.server.rule.ws.SearchAction.defineGenericRuleSearchParameters;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_DEACTIVATE_RULES;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_KEY;
@@ -67,7 +67,7 @@ public class DeactivateRulesAction implements QProfileWsAction {
.setSince("4.4")
.setHandler(this);
- defineRuleSearchParameters(deactivate);
+ defineGenericRuleSearchParameters(deactivate);
deactivate.createParam(PARAM_TARGET_KEY)
.setDescription("Quality Profile key on which the rule deactivation is done. To retrieve a profile key please see <code>api/qualityprofiles/search</code>")
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java
index a197a0ee8b9..8188955280c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java
@@ -67,6 +67,16 @@ public class RuleQueryFactory {
}
/**
+ * Similar to {@link #createRuleQuery(DbSession, Request)} but sets additional fields which are only used
+ * for the rule search WS.
+ */
+ public RuleQuery createRuleSearchQuery(DbSession dbSession, Request request) {
+ RuleQuery query = createRuleQuery(dbSession, request);
+ query.setIsExternal(request.paramAsBoolean(PARAM_IS_EXTERNAL));
+ return query;
+ }
+
+ /**
* Create a {@link RuleQuery} from a {@link Request}.
* When a profile key is set, the language of the profile is automatically set in the query
*/
@@ -92,7 +102,6 @@ public class RuleQueryFactory {
query.setInheritance(request.paramAsStrings(PARAM_INHERITANCE));
query.setActiveSeverities(request.paramAsStrings(PARAM_ACTIVE_SEVERITIES));
query.setIsTemplate(request.paramAsBoolean(PARAM_IS_TEMPLATE));
- query.setIsExternal(request.paramAsBoolean(PARAM_IS_EXTERNAL));
query.setTemplateKey(request.param(PARAM_TEMPLATE_KEY));
query.setTypes(toEnums(request.paramAsStrings(PARAM_TYPES), RuleType.class));
query.setKey(request.param(PARAM_RULE_KEY));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java
index 06ee60ec50b..50009dc6730 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java
@@ -96,9 +96,9 @@ public class RulesWsParameters {
public static final String FIELD_PARAMS = "params";
public static final String FIELD_ACTIVES = "actives";
- public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_REPO, FIELD_NAME, FIELD_CREATED_AT, FIELD_SEVERITY, FIELD_STATUS, FIELD_INTERNAL_KEY, FIELD_IS_EXTERNAL, FIELD_IS_TEMPLATE,
- FIELD_TEMPLATE_KEY, FIELD_TAGS, FIELD_SYSTEM_TAGS, FIELD_LANGUAGE, FIELD_LANGUAGE_NAME, FIELD_HTML_DESCRIPTION, FIELD_MARKDOWN_DESCRIPTION, FIELD_NOTE_LOGIN,
- FIELD_MARKDOWN_NOTE, FIELD_HTML_NOTE,
+ public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_REPO, FIELD_NAME, FIELD_CREATED_AT, FIELD_SEVERITY, FIELD_STATUS, FIELD_INTERNAL_KEY,
+ FIELD_IS_EXTERNAL, FIELD_IS_TEMPLATE, FIELD_TEMPLATE_KEY, FIELD_TAGS, FIELD_SYSTEM_TAGS, FIELD_LANGUAGE, FIELD_LANGUAGE_NAME, FIELD_HTML_DESCRIPTION,
+ FIELD_MARKDOWN_DESCRIPTION, FIELD_NOTE_LOGIN, FIELD_MARKDOWN_NOTE, FIELD_HTML_NOTE,
FIELD_DEFAULT_DEBT_REM_FUNCTION, FIELD_EFFORT_TO_FIX_DESCRIPTION, FIELD_DEBT_OVERLOADED, FIELD_DEBT_REM_FUNCTION,
FIELD_DEFAULT_REM_FUNCTION, FIELD_GAP_DESCRIPTION, FIELD_REM_FUNCTION_OVERLOADED, FIELD_REM_FUNCTION,
FIELD_PARAMS, FIELD_ACTIVES, FIELD_SCOPE);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
index 27349801230..2c9270c2656 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
@@ -135,7 +135,7 @@ public class SearchAction implements RulesWsAction {
.setChangelog(new Change("7.1", "The field 'scope' has been added to the response"))
.setChangelog(new Change("7.1", "The field 'scope' has been added to the 'f' parameter"))
.setChangelog(new Change("7.2", "The field 'isExternal' has been added to the response"))
- .setChangelog(new Change("7.2", "The field 'isExternal' has been added to the 'f' parameter"));;
+ .setChangelog(new Change("7.2", "The field 'isExternal' has been added to the 'f' parameter"));
action.createParam(FACETS)
.setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
@@ -163,7 +163,7 @@ public class SearchAction implements RulesWsAction {
try (DbSession dbSession = dbClient.openSession(false)) {
SearchRequest searchWsRequest = toSearchWsRequest(request);
SearchOptions context = buildSearchOptions(searchWsRequest);
- RuleQuery query = ruleQueryFactory.createRuleQuery(dbSession, request);
+ RuleQuery query = ruleQueryFactory.createRuleSearchQuery(dbSession, request);
SearchResult searchResult = doSearch(dbSession, query, context);
SearchResponse responseBuilder = buildResponse(dbSession, searchWsRequest, context, searchResult, query);
writeProtobuf(responseBuilder, request, response);
@@ -202,10 +202,16 @@ public class SearchAction implements RulesWsAction {
.setHandler(this);
// Rule-specific search parameters
- defineRuleSearchParameters(action);
+ defineGenericRuleSearchParameters(action);
+
+ action
+ .createParam(PARAM_IS_EXTERNAL)
+ .setDescription("Filter external engine rules")
+ .setBooleanPossibleValues()
+ .setSince("7.2");
}
- public static void defineRuleSearchParameters(WebService.NewAction action) {
+ public static void defineGenericRuleSearchParameters(WebService.NewAction action) {
action
.createParam(TEXT_QUERY)
.setMinimumLength(2)
@@ -296,12 +302,6 @@ public class SearchAction implements RulesWsAction {
.setBooleanPossibleValues();
action
- .createParam(PARAM_IS_EXTERNAL)
- .setDescription("Filter external engine rules")
- .setBooleanPossibleValues()
- .setSince("7.2");
-
- action
.createParam(PARAM_TEMPLATE_KEY)
.setDescription("Key of the template rule to filter on. Used to search for the custom rules based on this template.")
.setExampleValue("java:S001");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculatorTest.java
index 8024f1b121f..2314d14056e 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculatorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculatorTest.java
@@ -24,8 +24,8 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.sonar.api.rule.RuleKey;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.db.protobuf.DbCommons.TextRange;
@@ -51,14 +51,18 @@ import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
public class IssueCreationDateCalculatorTest {
private static final String COMPONENT_UUID = "ab12";
- @Rule
+ @org.junit.Rule
public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
+ @org.junit.Rule
+ public ExpectedException exception = ExpectedException.none();
+
private ScmInfoRepository scmInfoRepository = mock(ScmInfoRepository.class);
private IssueFieldsSetter issueUpdater = mock(IssueFieldsSetter.class);
private ActiveRulesHolder activeRulesHolder = mock(ActiveRulesHolder.class);
@@ -71,6 +75,7 @@ public class IssueCreationDateCalculatorTest {
private Map<String, ScannerPlugin> scannerPlugins = new HashMap<>();
private RuleRepository ruleRepository = mock(RuleRepository.class);
private ScmInfo scmInfo;
+ private Rule rule = mock(Rule.class);
@Before
public void before() {
@@ -79,6 +84,7 @@ public class IssueCreationDateCalculatorTest {
when(component.getUuid()).thenReturn(COMPONENT_UUID);
calculator = new IssueCreationDateCalculator(analysisMetadataHolder, scmInfoRepository, issueUpdater, activeRulesHolder, ruleRepository);
+ when(ruleRepository.findByKey(ruleKey)).thenReturn(java.util.Optional.of(rule));
when(activeRulesHolder.get(any(RuleKey.class)))
.thenReturn(Optional.absent());
when(activeRulesHolder.get(ruleKey))
@@ -163,6 +169,19 @@ public class IssueCreationDateCalculatorTest {
}
@Test
+ public void should_fail_if_rule_is_not_found() {
+ previousAnalysisWas(2000L);
+ currentAnalysisIs(3000L);
+
+ when(ruleRepository.findByKey(ruleKey)).thenReturn(java.util.Optional.empty());
+ newIssue();
+
+ exception.expect(IllegalStateException.class);
+ exception.expectMessage("The rule with key 'reop:rule' raised an issue, but no rule with that key was found");
+ run();
+ }
+
+ @Test
public void should_change_date_if_scm_is_available_and_rule_is_new() {
previousAnalysisWas(2000L);
currentAnalysisIs(3000L);
@@ -223,6 +242,23 @@ public class IssueCreationDateCalculatorTest {
}
@Test
+ public void should_backdate_external_issues() {
+ analysisMetadataHolder.setBaseAnalysis(null);
+ currentAnalysisIs(3000L);
+
+ newIssue();
+ when(rule.isExternal()).thenReturn(true);
+ when(issue.getLocations()).thenReturn(DbIssues.Locations.newBuilder().setTextRange(range(2, 3)).build());
+ withScmAt(2, 1200L);
+ withScmAt(3, 1300L);
+
+ run();
+
+ assertChangeOfCreationDateTo(1300L);
+ verifyZeroInteractions(activeRulesHolder);
+ }
+
+ @Test
public void should_use_primary_location_when_backdating() {
analysisMetadataHolder.setBaseAnalysis(null);
currentAnalysisIs(3000L);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistExternalRulesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistExternalRulesStepTest.java
index 219470ccf18..5ebab963bae 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistExternalRulesStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistExternalRulesStepTest.java
@@ -23,7 +23,6 @@ import java.util.Optional;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
@@ -58,7 +57,7 @@ public class PersistExternalRulesStepTest extends BaseStepTest {
private RuleRepositoryImpl ruleRepository;
@org.junit.Rule
- public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
+ public EsTester es = EsTester.create();
private RuleIndexer indexer = new RuleIndexer(es.client(), dbClient);
private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE, indexer);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistIssuesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistIssuesStepTest.java
index 0b4eaa16e1e..5e6ae3631eb 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistIssuesStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistIssuesStepTest.java
@@ -27,7 +27,6 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.System2;
@@ -53,7 +52,6 @@ import org.sonar.server.computation.task.projectanalysis.issue.UpdateConflictRes
import org.sonar.server.computation.task.step.ComputationStep;
import org.sonar.server.es.EsTester;
import org.sonar.server.rule.ExternalRuleCreator;
-import org.sonar.server.rule.index.RuleIndexDefinition;
import org.sonar.server.util.cache.DiskCache;
import static java.util.Collections.singletonList;
@@ -78,7 +76,7 @@ public class PersistIssuesStepTest extends BaseStepTest {
public BatchReportReaderRule reportReader = new BatchReportReaderRule();
@Rule
public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
- .setOrganizationUuid("org-1","qg-uuid-1");
+ .setOrganizationUuid("org-1", "qg-uuid-1");
private DbSession session = db.getSession();
private DbClient dbClient = db.getDbClient();
@@ -87,7 +85,7 @@ public class PersistIssuesStepTest extends BaseStepTest {
private ComputationStep step;
@org.junit.Rule
- public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
+ public EsTester es = EsTester.create();
private ExternalRuleCreator externalRuleCreator = mock(ExternalRuleCreator.class);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java
index ca23d02eb4a..c338d771a5d 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java
@@ -20,7 +20,6 @@
package org.sonar.server.rule;
import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.System2;
import org.sonar.db.DbSession;
@@ -28,7 +27,6 @@ import org.sonar.db.DbTester;
import org.sonar.server.computation.task.projectanalysis.issue.NewExternalRule;
import org.sonar.server.computation.task.projectanalysis.issue.Rule;
import org.sonar.server.es.EsTester;
-import org.sonar.server.rule.index.RuleIndexDefinition;
import org.sonar.server.rule.index.RuleIndexer;
import static org.assertj.core.api.Assertions.assertThat;
@@ -40,8 +38,8 @@ public class ExternalRuleCreatorTest {
@org.junit.Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
@org.junit.Rule
- public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
-
+ public EsTester es = EsTester.create();
+
private RuleIndexer indexer = new RuleIndexer(es.client(), dbTester.getDbClient());
private ExternalRuleCreator underTest = new ExternalRuleCreator(dbTester.getDbClient(), System2.INSTANCE, indexer);
private DbSession dbSession = dbTester.getSession();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java
index 455a9a84193..5a72e8fb77f 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java
@@ -397,18 +397,18 @@ public class RuleIndexTest {
SearchIdResult<Integer> results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).hasSize(2);
- // Only template
- query = new RuleQuery().setIsTemplate(true);
+ // Only external
+ query = new RuleQuery().setIsExternal(true);
results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).containsOnly(ruleIsExternal.getId());
- // Only not template
- query = new RuleQuery().setIsTemplate(false);
+ // Only not external
+ query = new RuleQuery().setIsExternal(false);
results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).containsOnly(ruleIsNotExternal.getId());
// null => no filter
- query = new RuleQuery().setIsTemplate(null);
+ query = new RuleQuery().setIsExternal(null);
results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).containsOnly(ruleIsExternal.getId(), ruleIsNotExternal.getId());
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java
index 49edcf25723..62ba7c6f33a 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java
@@ -152,7 +152,6 @@ public class RuleQueryFactoryTest {
assertThat(result.isAscendingSort()).isFalse();
assertThat(result.getAvailableSinceLong()).isNotNull();
assertThat(result.getInheritance()).containsOnly(INHERITED, OVERRIDES);
- assertThat(result.isExternal()).isTrue();
assertThat(result.isTemplate()).isTrue();
assertThat(result.getLanguages()).containsOnly(qualityProfile.getLanguage());
assertThat(result.getQueryText()).isEqualTo("S001");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java
index 450ee184427..82cc8dfb3de 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java
@@ -132,7 +132,7 @@ public class SearchActionTest {
assertThat(def.since()).isEqualTo("4.4");
assertThat(def.isInternal()).isFalse();
assertThat(def.responseExampleAsString()).isNotEmpty();
- assertThat(def.params()).hasSize(23);
+ assertThat(def.params()).hasSize(24);
WebService.Param compareToProfile = def.param("compareToProfile");
assertThat(compareToProfile.since()).isEqualTo("6.5");
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java
index 694942984c2..c845eb1ab7f 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java
@@ -23,6 +23,7 @@ import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import javax.annotation.Nullable;
import org.sonar.api.batch.sensor.internal.DefaultStorable;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.IssueLocation;
@@ -43,7 +44,7 @@ public abstract class AbstractDefaultIssue<T extends AbstractDefaultIssue> exte
super(null);
}
- public AbstractDefaultIssue(SensorStorage storage) {
+ public AbstractDefaultIssue(@Nullable SensorStorage storage) {
super(storage);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java
index 6bbf40078e7..6ffcb5055e8 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java
@@ -42,7 +42,7 @@ public class DefaultExternalIssue extends AbstractDefaultIssue<DefaultExternalIs
super(null);
}
- public DefaultExternalIssue(SensorStorage storage) {
+ public DefaultExternalIssue(@Nullable SensorStorage storage) {
super(storage);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java
index 30095731169..19f53a68af1 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java
@@ -39,7 +39,7 @@ public class DefaultIssue extends AbstractDefaultIssue<DefaultIssue> implements
super(null);
}
- public DefaultIssue(SensorStorage storage) {
+ public DefaultIssue(@Nullable SensorStorage storage) {
super(storage);
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ModuleIssues.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ModuleIssues.java
index a6bdaad62f2..1ff50f8e5b5 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ModuleIssues.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ModuleIssues.java
@@ -111,7 +111,7 @@ public class ModuleIssues {
}
private static ScannerReport.ExternalIssue createReportExternalIssue(ExternalIssue issue, int componentRef) {
- String primaryMessage = issue.primaryLocation().message();
+ String primaryMessage = Strings.isNullOrEmpty(issue.primaryLocation().message()) ? issue.ruleTitle() : issue.primaryLocation().message();
Severity severity = Severity.valueOf(issue.severity().name());
ScannerReport.ExternalIssue.Builder builder = ScannerReport.ExternalIssue.newBuilder();