aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java4
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java2
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java5
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleForIndexingDto.java5
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml1
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java12
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImpl.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java23
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleDoc.java10
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java20
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleQuery.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java8
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java2
-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.java11
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/rule/ws/example-show.json1
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/rule/ws/search-example.json5
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImplTest.java25
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistExternalRulesStepTest.java30
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistIssuesStepTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java30
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java10
-rw-r--r--sonar-ws/src/main/protobuf/ws-rules.proto1
28 files changed, 199 insertions, 52 deletions
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
index 58c0c97ec50..f062fee4298 100644
--- a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
@@ -146,8 +146,10 @@ import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import org.sonar.server.rule.CommonRuleDefinitionsImpl;
import org.sonar.server.rule.DefaultRuleFinder;
import org.sonar.server.rule.DeprecatedRulesDefinitionLoader;
+import org.sonar.server.rule.ExternalRuleCreator;
import org.sonar.server.rule.RuleDefinitionsLoader;
import org.sonar.server.rule.index.RuleIndex;
+import org.sonar.server.rule.index.RuleIndexer;
import org.sonar.server.setting.DatabaseSettingLoader;
import org.sonar.server.setting.DatabaseSettingsEnabler;
import org.sonar.server.setting.ThreadLocalSettings;
@@ -343,6 +345,8 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
CommonRuleDefinitionsImpl.class,
RuleDefinitionsLoader.class,
RulesDefinitionXmlLoader.class,
+ ExternalRuleCreator.class,
+ RuleIndexer.class,
// languages
Languages.class, // used by CommonRuleDefinitionsImpl
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
index 158f9ebe545..af333c9683d 100644
--- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
@@ -93,7 +93,7 @@ public class ComputeEngineContainerImplTest {
assertThat(picoContainer.getComponentAdapters())
.hasSize(
CONTAINER_ITSELF
- + 81 // level 4
+ + 83 // level 4
+ 21 // content of QualityGateModule
+ 6 // content of CeConfigurationModule
+ 4 // content of CeQueueModule
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java
index 38075e93fc5..6d5d64c9eca 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java
@@ -181,6 +181,11 @@ public class RuleDto {
return definition.isExternal();
}
+ public RuleDto setIsExternal(boolean isExternal) {
+ definition.setIsExternal(isExternal);
+ return this;
+ }
+
public boolean isTemplate() {
return definition.isTemplate();
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleForIndexingDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleForIndexingDto.java
index 9840e9207d8..0a42c354613 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleForIndexingDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleForIndexingDto.java
@@ -42,6 +42,7 @@ public class RuleForIndexingDto {
private String templateRepository;
private String internalKey;
private String language;
+ private boolean isExternal;
private int type;
private long createdAt;
private long updatedAt;
@@ -107,6 +108,10 @@ public class RuleForIndexingDto {
public int getType() {
return type;
}
+
+ public boolean isExternal() {
+ return isExternal;
+ }
public long getCreatedAt() {
return createdAt;
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml
index 0d5acbf4bba..3aa294ff91d 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml
@@ -252,6 +252,7 @@
r.priority as "severity",
r.status as "status",
r.is_template as "isTemplate",
+ r.is_external as "isExternal",
r.system_tags as "systemTags",
t.plugin_rule_key as "templateRuleKey",
t.plugin_name as "templateRepository",
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java
index 44e469219f9..99d2e4555c4 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java
@@ -23,6 +23,7 @@ import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -360,6 +361,7 @@ public class RuleDaoTest {
assertThat(actual.getConfigKey()).isEqualTo(expected.getConfigKey());
assertThat(actual.getSeverity()).isEqualTo(expected.getSeverity());
assertThat(actual.getSeverityString()).isEqualTo(expected.getSeverityString());
+ assertThat(actual.isExternal()).isEqualTo(expected.isExternal());
assertThat(actual.isTemplate()).isEqualTo(expected.isTemplate());
assertThat(actual.getLanguage()).isEqualTo(expected.getLanguage());
assertThat(actual.getTemplateId()).isEqualTo(expected.getTemplateId());
@@ -809,14 +811,15 @@ public class RuleDaoTest {
public void scrollIndexingRules() {
Accumulator<RuleForIndexingDto> accumulator = new Accumulator<>();
RuleDefinitionDto r1 = db.rules().insert();
- RuleDefinitionDto r2 = db.rules().insert();
+ RuleDefinitionDto r2 = db.rules().insert(r -> r.setIsExternal(true));
underTest.scrollIndexingRules(db.getSession(), accumulator);
assertThat(accumulator.list)
.extracting(RuleForIndexingDto::getId, RuleForIndexingDto::getRuleKey)
.containsExactlyInAnyOrder(tuple(r1.getId(), r1.getKey()), tuple(r2.getId(), r2.getKey()));
- RuleForIndexingDto firstRule = accumulator.list.iterator().next();
+ Iterator<RuleForIndexingDto> it = accumulator.list.iterator();
+ RuleForIndexingDto firstRule = it.next();
assertThat(firstRule.getRepository()).isEqualTo(r1.getRepositoryKey());
assertThat(firstRule.getPluginRuleKey()).isEqualTo(r1.getRuleKey());
@@ -825,6 +828,7 @@ public class RuleDaoTest {
assertThat(firstRule.getDescriptionFormat()).isEqualTo(r1.getDescriptionFormat());
assertThat(firstRule.getSeverity()).isEqualTo(r1.getSeverity());
assertThat(firstRule.getStatus()).isEqualTo(r1.getStatus());
+ assertThat(firstRule.isExternal()).isFalse();
assertThat(firstRule.isTemplate()).isEqualTo(r1.isTemplate());
assertThat(firstRule.getSystemTagsAsSet()).isEqualTo(r1.getSystemTags());
assertThat(firstRule.getTemplateRuleKey()).isNull();
@@ -834,6 +838,10 @@ public class RuleDaoTest {
assertThat(firstRule.getType()).isEqualTo(r1.getType());
assertThat(firstRule.getCreatedAt()).isEqualTo(r1.getCreatedAt());
assertThat(firstRule.getUpdatedAt()).isEqualTo(r1.getUpdatedAt());
+
+ RuleForIndexingDto secondRule = it.next();
+ assertThat(secondRule.isExternal()).isTrue();
+
}
@Test
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java
index 3339cc08120..77b70a3ecff 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java
@@ -305,6 +305,10 @@ public class RuleTesting {
public static Consumer<RuleDefinitionDto> setType(RuleType type) {
return rule -> rule.setType(type);
}
+
+ public static Consumer<RuleDefinitionDto> setIsExternal(boolean isExternal) {
+ return rule -> rule.setIsExternal(isExternal);
+ }
public static Consumer<RuleDefinitionDto> setIsTemplate(boolean isTemplate) {
return rule -> rule.setIsTemplate(isTemplate);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java
index b7692f5cb56..f40d4dece13 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java
@@ -122,7 +122,6 @@ import org.sonar.server.computation.task.projectanalysis.webhook.WebhookPostTask
import org.sonar.server.computation.task.step.ComputationStepExecutor;
import org.sonar.server.computation.task.step.ComputationSteps;
import org.sonar.server.computation.taskprocessor.MutableTaskResultHolderImpl;
-import org.sonar.server.rule.ExternalRuleCreator;
import org.sonar.server.view.index.ViewIndex;
public final class ProjectAnalysisTaskContainerPopulator implements ContainerPopulator<TaskContainer> {
@@ -197,7 +196,6 @@ public final class ProjectAnalysisTaskContainerPopulator implements ContainerPop
DuplicationRepositoryImpl.class,
// issues
- ExternalRuleCreator.class,
RuleRepositoryImpl.class,
ScmAccountToUserLoader.class,
ScmAccountToUser.class,
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 10eb88f7e09..b29dea960cd 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
@@ -72,7 +72,7 @@ public class RuleRepositoryImpl implements RuleRepository {
}
private void persistAndIndex(DbSession dbSession, NewExternalRule external) {
- Rule rule = creator.create(dbSession, external);
+ Rule rule = creator.persistAndIndex(dbSession, external);
rulesById.put(rule.getId(), rule);
rulesByKey.put(external.getKey(), rule);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java
index 2cbef97cbd5..31f4467ff18 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java
@@ -19,7 +19,7 @@
*/
package org.sonar.server.rule;
-import org.sonar.api.server.ServerSide;
+import org.sonar.api.rule.RuleStatus;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
@@ -28,34 +28,45 @@ import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.server.computation.task.projectanalysis.issue.NewExternalRule;
import org.sonar.server.computation.task.projectanalysis.issue.Rule;
import org.sonar.server.computation.task.projectanalysis.issue.RuleImpl;
+import org.sonar.server.rule.index.RuleIndexer;
import static org.sonar.db.rule.RuleDto.Scope.ALL;
-@ServerSide
public class ExternalRuleCreator {
private final DbClient dbClient;
private final System2 system2;
+ private final RuleIndexer ruleIndexer;
- public ExternalRuleCreator(DbClient dbClient, System2 system2) {
+ public ExternalRuleCreator(DbClient dbClient, System2 system2, RuleIndexer ruleIndexer) {
this.dbClient = dbClient;
this.system2 = system2;
+ this.ruleIndexer = ruleIndexer;
}
- public Rule create(DbSession dbSession, NewExternalRule external) {
+ /**
+ * Persists a rule in the DB and indexes it.
+ * @return the rule that was inserted in the DB, which <b>includes the generated ID</b>.
+ */
+ public Rule persistAndIndex(DbSession dbSession, NewExternalRule external) {
RuleDao dao = dbClient.ruleDao();
dao.insert(dbSession, new RuleDefinitionDto()
.setRuleKey(external.getKey())
.setPluginKey(external.getPluginKey())
- .setIsExternal(true)
+ .setIsExternal(external.isExternal())
.setName(external.getName())
.setDescriptionURL(external.getDescriptionUrl())
.setType(external.getType())
.setScope(ALL)
+ .setStatus(RuleStatus.READY)
.setSeverity(external.getSeverity())
.setCreatedAt(system2.now())
.setUpdatedAt(system2.now()));
- return new RuleImpl(dao.selectOrFailByKey(dbSession, external.getKey()));
+
+ Rule newRule = new RuleImpl(dao.selectOrFailByKey(dbSession, external.getKey()));
+ // TODO write rule repository if needed
+ ruleIndexer.commitAndIndex(dbSession, newRule.getId());
+ return newRule;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java
index 3ffb85b521f..9f9d1ce3764 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java
@@ -391,6 +391,7 @@ public class RegisterRules implements Startable {
.setSystemTags(ruleDef.tags())
.setType(RuleType.valueOf(ruleDef.type().name()))
.setScope(toDtoScope(ruleDef.scope()))
+ .setIsExternal(false)
.setCreatedAt(system2.now())
.setUpdatedAt(system2.now());
if (ruleDef.htmlDescription() != null) {
@@ -633,7 +634,7 @@ public class RegisterRules implements Startable {
recorder.getRemaining().forEach(rule -> {
if (rule.isCustomRule()) {
customRules.add(rule);
- } else if (rule.getStatus() != RuleStatus.REMOVED) {
+ } else if (!rule.isExternal() && rule.getStatus() != RuleStatus.REMOVED) {
removeRule(dbSession, recorder, rule);
}
});
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleDoc.java b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleDoc.java
index 4645f7ce6d8..f413798dc89 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleDoc.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleDoc.java
@@ -181,6 +181,15 @@ public class RuleDoc extends BaseDoc {
return this;
}
+ public boolean isExternal() {
+ return getField(RuleIndexDefinition.FIELD_RULE_IS_EXTERNAL);
+ }
+
+ public RuleDoc setIsExternal(boolean b) {
+ setField(RuleIndexDefinition.FIELD_RULE_IS_EXTERNAL, b);
+ return this;
+ }
+
public RuleType type() {
return RuleType.valueOf(getField(RuleIndexDefinition.FIELD_RULE_TYPE));
}
@@ -220,6 +229,7 @@ public class RuleDoc extends BaseDoc {
.setRepository(dto.getRepository())
.setInternalKey(dto.getInternalKey())
.setIsTemplate(dto.isTemplate())
+ .setIsExternal(dto.isExternal())
.setLanguage(dto.getLanguage())
.setName(dto.getName())
.setRuleKey(dto.getPluginRuleKey())
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
index 25f98b5098f..d93d6fc5893 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
@@ -93,6 +93,7 @@ import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_EXTENSI
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_EXTENSION_TAGS;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_HTML_DESCRIPTION;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_INTERNAL_KEY;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_IS_EXTERNAL;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_IS_TEMPLATE;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_KEY;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_LANGUAGE;
@@ -205,13 +206,12 @@ public class RuleIndex {
.stream().map(token -> boolQuery().should(
matchQuery(
SEARCH_GRAMS_ANALYZER.subField(FIELD_RULE_NAME),
- StringUtils.left(token, DefaultIndexSettings.MAXIMUM_NGRAM_LENGTH)
- ).boost(20f)).should(
- matchPhraseQuery(
- ENGLISH_HTML_ANALYZER.subField(FIELD_RULE_HTML_DESCRIPTION),
- token
- ).boost(3f))
- ).forEach(textQuery::must);
+ StringUtils.left(token, DefaultIndexSettings.MAXIMUM_NGRAM_LENGTH)).boost(20f))
+ .should(
+ matchPhraseQuery(
+ ENGLISH_HTML_ANALYZER.subField(FIELD_RULE_HTML_DESCRIPTION),
+ token).boost(3f)))
+ .forEach(textQuery::must);
qb.should(textQuery.boost(20f));
}
@@ -302,6 +302,12 @@ public class RuleIndex {
QueryBuilders.termQuery(FIELD_RULE_IS_TEMPLATE, Boolean.toString(isTemplate)));
}
+ Boolean isExternal = query.isExternal();
+ if (isExternal != null) {
+ filters.put(FIELD_RULE_IS_EXTERNAL,
+ QueryBuilders.termQuery(FIELD_RULE_IS_EXTERNAL, Boolean.toString(isExternal)));
+ }
+
String template = query.templateKey();
if (template != null) {
filters.put(FIELD_RULE_TEMPLATE_KEY,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java
index 38e54fcb4b0..63567d83026 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java
@@ -53,6 +53,7 @@ public class RuleIndexDefinition implements IndexDefinition {
public static final String FIELD_RULE_STATUS = "status";
public static final String FIELD_RULE_LANGUAGE = "lang";
public static final String FIELD_RULE_IS_TEMPLATE = "isTemplate";
+ public static final String FIELD_RULE_IS_EXTERNAL = "isExternal";
public static final String FIELD_RULE_TEMPLATE_KEY = "templateKey";
public static final String FIELD_RULE_TYPE = "type";
public static final String FIELD_RULE_CREATED_AT = "createdAt";
@@ -154,6 +155,7 @@ public class RuleIndexDefinition implements IndexDefinition {
ruleMapping.keywordFieldBuilder(FIELD_RULE_LANGUAGE).disableNorms().build();
ruleMapping.createBooleanField(FIELD_RULE_IS_TEMPLATE);
+ ruleMapping.createBooleanField(FIELD_RULE_IS_EXTERNAL);
ruleMapping.keywordFieldBuilder(FIELD_RULE_TEMPLATE_KEY).disableNorms().build();
ruleMapping.keywordFieldBuilder(FIELD_RULE_TYPE).disableNorms().build();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleQuery.java b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleQuery.java
index e0b6f3040a4..4b79ffcfcd9 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleQuery.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleQuery.java
@@ -54,6 +54,7 @@ public class RuleQuery {
private String internalKey;
private String ruleKey;
private OrganizationDto organization;
+ private Boolean isExternal;
@CheckForNull
public QProfileDto getQProfile() {
@@ -206,6 +207,16 @@ public class RuleQuery {
}
@CheckForNull
+ public Boolean isExternal() {
+ return isExternal;
+ }
+
+ public RuleQuery setIsExternal(@Nullable Boolean b) {
+ this.isExternal = b;
+ return this;
+ }
+
+ @CheckForNull
public String templateKey() {
return templateKey;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java
index 09790900602..9a70c738b52 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java
@@ -52,6 +52,7 @@ import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_EFFORT_TO_FIX_DES
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_GAP_DESCRIPTION;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_HTML_DESCRIPTION;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_INTERNAL_KEY;
+import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_IS_EXTERNAL;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_IS_TEMPLATE;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_LANGUAGE;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_LANGUAGE_NAME;
@@ -115,6 +116,7 @@ public class RuleMapper {
setLanguage(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setLanguageName(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setIsTemplate(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setIsExternal(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setTemplateKey(ruleResponse, ruleDefinitionDto, result, fieldsToReturn);
setDefaultDebtRemediationFunctionFields(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setEffortToFixDescription(ruleResponse, ruleDefinitionDto, fieldsToReturn);
@@ -323,6 +325,12 @@ public class RuleMapper {
ruleResponse.setIsTemplate(ruleDto.isTemplate());
}
}
+
+ private static void setIsExternal(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
+ if (shouldReturnField(fieldsToReturn, FIELD_IS_EXTERNAL)) {
+ ruleResponse.setIsExternal(ruleDto.isExternal());
+ }
+ }
private static void setTemplateKey(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, SearchResult result, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_TEMPLATE_KEY) && ruleDto.isCustomRule()) {
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 75baf8a2e4d..a197a0ee8b9 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
@@ -43,6 +43,7 @@ import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_COMPARE_TO_PROFILE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_INHERITANCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_TEMPLATE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_EXTERNAL;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ORGANIZATION;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE;
@@ -91,6 +92,7 @@ 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 9b87af2679f..06ee60ec50b 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
@@ -36,6 +36,7 @@ public class RulesWsParameters {
public static final String PARAM_INHERITANCE = "inheritance";
public static final String PARAM_ACTIVE_SEVERITIES = "active_severities";
public static final String PARAM_IS_TEMPLATE = "is_template";
+ public static final String PARAM_IS_EXTERNAL = "is_external";
public static final String PARAM_TEMPLATE_KEY = "template_key";
public static final String PARAM_ORGANIZATION = "organization";
public static final String PARAM_COMPARE_TO_PROFILE = "compareToProfile";
@@ -46,6 +47,7 @@ public class RulesWsParameters {
public static final String FIELD_SEVERITY = "severity";
public static final String FIELD_STATUS = "status";
public static final String FIELD_INTERNAL_KEY = "internalKey";
+ public static final String FIELD_IS_EXTERNAL = "isExternal";
public static final String FIELD_IS_TEMPLATE = "isTemplate";
public static final String FIELD_TEMPLATE_KEY = "templateKey";
public static final String FIELD_TAGS = "tags";
@@ -90,11 +92,11 @@ public class RulesWsParameters {
* @since 7.1
*/
public static final String FIELD_SCOPE = "scope";
-
+
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_TEMPLATE,
+ 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,
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 856ecf74362..27349801230 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
@@ -85,6 +85,7 @@ import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_COMPARE_TO_PROFILE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_INHERITANCE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_EXTERNAL;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_TEMPLATE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ORGANIZATION;
@@ -132,7 +133,9 @@ public class SearchAction implements RulesWsAction {
.addPagingParams(100, MAX_LIMIT)
.setHandler(this)
.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.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"));;
action.createParam(FACETS)
.setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
@@ -293,6 +296,12 @@ 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/main/resources/org/sonar/server/rule/ws/example-show.json b/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/example-show.json
index b52d4c8c4c2..8664d1509fa 100644
--- a/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/example-show.json
+++ b/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/example-show.json
@@ -20,6 +20,7 @@
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "CODE_SMELL",
"params": [
{
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/search-example.json b/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/search-example.json
index 84c840898a8..2e5091ac51f 100644
--- a/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/search-example.json
+++ b/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/search-example.json
@@ -18,6 +18,7 @@
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "CODE_SMELL",
"params": [
{
@@ -42,6 +43,7 @@
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "BUG",
"params": [
{
@@ -66,6 +68,7 @@
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "VULNERABILITY",
"params": [
{
@@ -93,6 +96,7 @@
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "CODE_SMELL",
"params": [
{
@@ -123,6 +127,7 @@
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "CODE_SMELL",
"params": [
{
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImplTest.java
index 318f4e4ca7b..39d085ad39c 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImplTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImplTest.java
@@ -21,6 +21,7 @@ package org.sonar.server.computation.task.projectanalysis.issue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
@@ -41,6 +42,7 @@ import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetada
import org.sonar.server.es.EsTester;
import org.sonar.server.rule.ExternalRuleCreator;
import org.sonar.server.rule.index.RuleIndexDefinition;
+import org.sonar.server.rule.index.RuleIndexer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -75,14 +77,13 @@ public class RuleRepositoryImplTest {
@org.junit.Rule
public DbTester db = DbTester.create(System2.INSTANCE);
- @org.junit.Rule
- public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
private DbClient dbClient = mock(DbClient.class);
private DbSession dbSession = mock(DbSession.class);
private RuleDao ruleDao = mock(RuleDao.class);
- private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
+ private RuleIndexer ruleIndexer = mock(RuleIndexer.class);
+ private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(db.getDbClient(), System2.INSTANCE, ruleIndexer);
private RuleRepositoryImpl underTest = new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder);
@Before
@@ -272,10 +273,6 @@ public class RuleRepositoryImplTest {
@Test
public void accept_new_externally_defined_Rules() {
- DbClient dbClient = db.getDbClient();
- externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
- underTest = new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder);
-
RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
underTest.insertNewExternalRuleIfAbsent(ruleKey, () -> new NewExternalRule.Builder()
@@ -299,10 +296,7 @@ public class RuleRepositoryImplTest {
@Test
public void persist_new_externally_defined_Rules() {
- DbClient dbClient = db.getDbClient();
- DbSession dbSession = dbClient.openSession(false);
- externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
- underTest = new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder);
+ underTest = new RuleRepositoryImpl(externalRuleCreator, db.getDbClient(), analysisMetadataHolder);
RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
underTest.insertNewExternalRuleIfAbsent(ruleKey, () -> new NewExternalRule.Builder()
@@ -314,18 +308,17 @@ public class RuleRepositoryImplTest {
.setType(BUG)
.build());
- underTest.persistNewExternalRules(dbSession);
-
- dbSession.commit();
+ underTest.persistNewExternalRules(db.getSession());
+ db.commit();
- RuleDao ruleDao = dbClient.ruleDao();
- Optional<RuleDefinitionDto> ruleDefinitionDto = ruleDao.selectDefinitionByKey(dbClient.openSession(false), ruleKey);
+ Optional<RuleDefinitionDto> ruleDefinitionDto = db.getDbClient().ruleDao().selectDefinitionByKey(db.getSession(), ruleKey);
assertThat(ruleDefinitionDto).isPresent();
Rule rule = underTest.getByKey(ruleKey);
assertThat(rule).isNotNull();
assertThat(underTest.getById(ruleDefinitionDto.get().getId())).isNotNull();
+ verify(ruleIndexer).commitAndIndex(db.getSession(), ruleDefinitionDto.get().getId());
}
private void expectNullRuleKeyNPE() {
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 d3f2a9d33db..219470ccf18 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
@@ -19,6 +19,7 @@
*/
package org.sonar.server.computation.task.projectanalysis.step;
+import java.util.Optional;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -36,8 +37,7 @@ 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 java.util.Optional;
+import org.sonar.server.rule.index.RuleIndexer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.rule.Severity.BLOCKER;
@@ -60,7 +60,8 @@ public class PersistExternalRulesStepTest extends BaseStepTest {
@org.junit.Rule
public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
- private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
+ private RuleIndexer indexer = new RuleIndexer(es.client(), dbClient);
+ private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE, indexer);
@Override
protected ComputationStep step() {
@@ -74,7 +75,7 @@ public class PersistExternalRulesStepTest extends BaseStepTest {
}
@Test
- public void persist_new_external_rules() {
+ public void persist_and_index_new_external_rules() {
RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
ruleRepository.insertNewExternalRuleIfAbsent(ruleKey, () -> new NewExternalRule.Builder()
@@ -102,7 +103,28 @@ public class PersistExternalRulesStepTest extends BaseStepTest {
assertThat(reloaded.getName()).isEqualTo("disallow assignment operators in conditional statements (no-cond-assign)");
assertThat(reloaded.getPluginKey()).isEqualTo("eslint");
+ assertThat(es.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isEqualTo(1l);
+ assertThat(es.getDocuments(RuleIndexDefinition.INDEX_TYPE_RULE).iterator().next().getId()).isEqualTo(Integer.toString(reloaded.getId()));
+ }
+
+ @Test
+ public void do_not_persist_existing_external_rules() {
+ RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
+ db.rules().insert(ruleKey, r -> r.setIsExternal(true));
+ ruleRepository.insertNewExternalRuleIfAbsent(ruleKey, () -> new NewExternalRule.Builder()
+ .setKey(ruleKey)
+ .setPluginKey("eslint")
+ .setName("disallow assignment operators in conditional statements (no-cond-assign)")
+ .setDescriptionUrl("https://eslint.org/docs/rules/no-cond-assign")
+ .setSeverity(BLOCKER)
+ .setType(BUG)
+ .build());
+
+ underTest.execute();
+ RuleDao ruleDao = dbClient.ruleDao();
+ assertThat(ruleDao.selectAllDefinitions(dbClient.openSession(false))).hasSize(1);
+ assertThat(es.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isZero();
}
}
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 e57c3dd6729..0b4eaa16e1e 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
@@ -89,7 +89,7 @@ public class PersistIssuesStepTest extends BaseStepTest {
@org.junit.Rule
public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
- private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
+ private ExternalRuleCreator externalRuleCreator = mock(ExternalRuleCreator.class);
@Override
protected ComputationStep step() {
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 2beeddfc76c..ca23d02eb4a 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,12 +20,16 @@
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;
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;
import static org.sonar.api.rule.Severity.BLOCKER;
@@ -35,13 +39,15 @@ public class ExternalRuleCreatorTest {
@org.junit.Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- private ExternalRuleCreator underTest = new ExternalRuleCreator(dbTester.getDbClient(), System2.INSTANCE);
+ @org.junit.Rule
+ public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
+
+ private RuleIndexer indexer = new RuleIndexer(es.client(), dbTester.getDbClient());
+ private ExternalRuleCreator underTest = new ExternalRuleCreator(dbTester.getDbClient(), System2.INSTANCE, indexer);
private DbSession dbSession = dbTester.getSession();
@Test
public void create_external_rule() {
-
RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
NewExternalRule externalRule = new NewExternalRule.Builder()
.setKey(ruleKey)
@@ -52,7 +58,7 @@ public class ExternalRuleCreatorTest {
.setType(BUG)
.build();
- Rule rule1 = underTest.create(dbSession, externalRule);
+ Rule rule1 = underTest.persistAndIndex(dbSession, externalRule);
assertThat(rule1).isNotNull();
assertThat(rule1.isExternal()).isTrue();
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 4c961c262dd..455a9a84193 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
@@ -63,6 +63,7 @@ import static org.sonar.api.rules.RuleType.CODE_SMELL;
import static org.sonar.api.rules.RuleType.VULNERABILITY;
import static org.sonar.db.rule.RuleTesting.setCreatedAt;
import static org.sonar.db.rule.RuleTesting.setIsTemplate;
+import static org.sonar.db.rule.RuleTesting.setIsExternal;
import static org.sonar.db.rule.RuleTesting.setLanguage;
import static org.sonar.db.rule.RuleTesting.setName;
import static org.sonar.db.rule.RuleTesting.setOrganization;
@@ -366,7 +367,7 @@ public class RuleIndexTest {
// find all
RuleQuery query = new RuleQuery();
- SearchIdResult results = underTest.search(query, new SearchOptions());
+ SearchIdResult<Integer> results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).hasSize(2);
// Only template
@@ -384,6 +385,33 @@ public class RuleIndexTest {
results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).containsOnly(ruleIsTemplate.getId(), ruleNoTemplate.getId());
}
+
+ @Test
+ public void search_by_is_external() {
+ RuleDefinitionDto ruleIsNotExternal = createRule(setIsExternal(false));
+ RuleDefinitionDto ruleIsExternal = createRule(setIsExternal(true));
+ index();
+
+ // find all
+ RuleQuery query = new RuleQuery();
+ SearchIdResult<Integer> results = underTest.search(query, new SearchOptions());
+ assertThat(results.getIds()).hasSize(2);
+
+ // Only template
+ query = new RuleQuery().setIsTemplate(true);
+ results = underTest.search(query, new SearchOptions());
+ assertThat(results.getIds()).containsOnly(ruleIsExternal.getId());
+
+ // Only not template
+ query = new RuleQuery().setIsTemplate(false);
+ results = underTest.search(query, new SearchOptions());
+ assertThat(results.getIds()).containsOnly(ruleIsNotExternal.getId());
+
+ // null => no filter
+ query = new RuleQuery().setIsTemplate(null);
+ results = underTest.search(query, new SearchOptions());
+ assertThat(results.getIds()).containsOnly(ruleIsExternal.getId(), ruleIsNotExternal.getId());
+ }
@Test
public void search_by_template_key() {
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 ea3c0761a6f..49edcf25723 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
@@ -51,13 +51,14 @@ import static org.sonar.api.server.ws.WebService.Param.SORT;
import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
import static org.sonar.db.qualityprofile.ActiveRuleDto.INHERITED;
import static org.sonar.db.qualityprofile.ActiveRuleDto.OVERRIDES;
-import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters;
+import static org.sonar.server.rule.ws.SearchAction.defineGenericRuleSearchParameters;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVATION;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_COMPARE_TO_PROFILE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_INHERITANCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_TEMPLATE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_EXTERNAL;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ORGANIZATION;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE;
@@ -99,6 +100,7 @@ public class RuleQueryFactoryTest {
assertThat(result.isAscendingSort()).isTrue();
assertThat(result.getAvailableSinceLong()).isNull();
assertThat(result.getInheritance()).isNull();
+ assertThat(result.isExternal()).isNull();
assertThat(result.isTemplate()).isNull();
assertThat(result.getLanguages()).isNull();
assertThat(result.getQueryText()).isNull();
@@ -126,7 +128,8 @@ public class RuleQueryFactoryTest {
PARAM_ACTIVE_SEVERITIES, "MINOR,MAJOR",
PARAM_AVAILABLE_SINCE, "2016-01-01",
PARAM_INHERITANCE, "INHERITED,OVERRIDES",
- PARAM_IS_TEMPLATE, "true",
+ PARAM_IS_TEMPLATE, "true",
+ PARAM_IS_EXTERNAL, "true",
PARAM_LANGUAGES, "java,js",
TEXT_QUERY, "S001",
PARAM_ORGANIZATION, organization.getKey(),
@@ -149,6 +152,7 @@ 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");
@@ -308,7 +312,7 @@ public class RuleQueryFactoryTest {
public void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction("fake")
.setHandler(this);
- defineRuleSearchParameters(action);
+ defineGenericRuleSearchParameters(action);
}
@Override
diff --git a/sonar-ws/src/main/protobuf/ws-rules.proto b/sonar-ws/src/main/protobuf/ws-rules.proto
index 7bca93aab8b..ee45d81f8b7 100644
--- a/sonar-ws/src/main/protobuf/ws-rules.proto
+++ b/sonar-ws/src/main/protobuf/ws-rules.proto
@@ -120,6 +120,7 @@ message Rule {
optional bool remFnOverloaded = 45;
optional string gapDescription = 44;
optional sonarqube.ws.commons.RuleScope scope = 46;
+ optional bool isExternal = 47;
optional sonarqube.ws.commons.RuleType type = 37;