Browse Source

SONAR-10357 add ruleId to BuiltInQProfile#activeRules

tags/7.5
Sébastien Lesaint 6 years ago
parent
commit
1aa398cc2f

+ 33
- 5
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfile.java View File

@@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.concurrent.Immutable;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;

/**
@@ -32,7 +33,7 @@ import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
public final class BuiltInQProfile {
private final QProfileName qProfileName;
private final boolean isDefault;
private final List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> activeRules;
private final List<ActiveRule> activeRules;

private BuiltInQProfile(Builder builder) {
this.qProfileName = new QProfileName(builder.language, builder.name);
@@ -56,16 +57,38 @@ public final class BuiltInQProfile {
return isDefault;
}

public List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> getActiveRules() {
public List<ActiveRule> getActiveRules() {
return activeRules;
}

static final class ActiveRule {
private final int ruleId;
private final BuiltInQualityProfilesDefinition.BuiltInActiveRule builtIn;

ActiveRule(int ruleId, BuiltInQualityProfilesDefinition.BuiltInActiveRule builtIn) {
this.ruleId = ruleId;
this.builtIn = builtIn;
}

public int getRuleId() {
return ruleId;
}

public RuleKey getRuleKey() {
return RuleKey.of(builtIn.repoKey(), builtIn.ruleKey());
}

public BuiltInQualityProfilesDefinition.BuiltInActiveRule getBuiltIn() {
return builtIn;
}
}

static final class Builder {
private String language;
private String name;
private boolean declaredDefault;
private boolean computedDefault;
private final List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> activeRules = new ArrayList<>();
private final List<ActiveRule> activeRules = new ArrayList<>();

public Builder setLanguage(String language) {
this.language = language;
@@ -95,8 +118,13 @@ public final class BuiltInQProfile {
return this;
}

Builder addRules(List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> rules) {
this.activeRules.addAll(rules);
Builder addRule(BuiltInQualityProfilesDefinition.BuiltInActiveRule rule, int ruleId) {
this.activeRules.add(new ActiveRule(ruleId, rule));
return this;
}

Builder addRule(ActiveRule activeRule) {
this.activeRules.add(activeRule);
return this;
}


+ 7
- 7
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImpl.java View File

@@ -139,8 +139,8 @@ public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert {
return dto;
}

private ActiveRuleChange insertActiveRule(DbSession dbSession, RulesProfileDto rulesProfileDto, BuiltInQualityProfilesDefinition.BuiltInActiveRule activeRule, long now) {
RuleKey ruleKey = RuleKey.of(activeRule.repoKey(), activeRule.ruleKey());
private ActiveRuleChange insertActiveRule(DbSession dbSession, RulesProfileDto rulesProfileDto, BuiltInQProfile.ActiveRule activeRule, long now) {
RuleKey ruleKey = activeRule.getRuleKey();
RuleDefinitionDto ruleDefinitionDto = ruleRepository.getDefinition(ruleKey)
.orElseThrow(() -> new IllegalStateException("RuleDefinition not found for key " + ruleKey));

@@ -148,12 +148,12 @@ public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert {
dto.setProfileId(rulesProfileDto.getId());
dto.setRuleId(ruleDefinitionDto.getId());
dto.setKey(ActiveRuleKey.of(rulesProfileDto, ruleDefinitionDto.getKey()));
dto.setSeverity(firstNonNull(activeRule.overriddenSeverity(), ruleDefinitionDto.getSeverityString()));
dto.setSeverity(firstNonNull(activeRule.getBuiltIn().overriddenSeverity(), ruleDefinitionDto.getSeverityString()));
dto.setUpdatedAt(now);
dto.setCreatedAt(now);
dbClient.activeRuleDao().insert(dbSession, dto);

List<ActiveRuleParamDto> paramDtos = insertActiveRuleParams(dbSession, activeRule, ruleKey, dto);
List<ActiveRuleParamDto> paramDtos = insertActiveRuleParams(dbSession, activeRule, dto);

ActiveRuleChange change = new ActiveRuleChange(ActiveRuleChange.Type.ACTIVATED, dto, ruleDefinitionDto);
change.setSeverity(dto.getSeverityString());
@@ -161,12 +161,12 @@ public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert {
return change;
}

private List<ActiveRuleParamDto> insertActiveRuleParams(DbSession session, BuiltInQualityProfilesDefinition.BuiltInActiveRule activeRule, RuleKey ruleKey,
private List<ActiveRuleParamDto> insertActiveRuleParams(DbSession session, BuiltInQProfile.ActiveRule activeRule,
ActiveRuleDto activeRuleDto) {
Map<String, String> valuesByParamKey = activeRule.overriddenParams()
Map<String, String> valuesByParamKey = activeRule.getBuiltIn().overriddenParams()
.stream()
.collect(MoreCollectors.uniqueIndex(BuiltInQualityProfilesDefinition.OverriddenParam::key, BuiltInQualityProfilesDefinition.OverriddenParam::overriddenValue));
return ruleRepository.getRuleParams(ruleKey)
return ruleRepository.getRuleParams(activeRule.getRuleKey())
.stream()
.map(param -> {
String activeRuleValue = valuesByParamKey.get(param.getName());

+ 53
- 24
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImpl.java View File

@@ -21,6 +21,7 @@ package org.sonar.server.qualityprofile;

import com.google.common.collect.ImmutableList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -29,12 +30,16 @@ import java.util.Set;
import javax.annotation.Nullable;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Languages;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInQualityProfile;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.rule.RuleDefinitionDto;

import static com.google.common.base.Preconditions.checkState;

@@ -42,6 +47,7 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository
private static final Logger LOGGER = Loggers.get(BuiltInQProfileRepositoryImpl.class);
private static final String DEFAULT_PROFILE_NAME = "Sonar way";

private final DbClient dbClient;
private final Languages languages;
private final List<BuiltInQualityProfilesDefinition> definitions;
private List<BuiltInQProfile> qProfiles;
@@ -49,11 +55,12 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository
/**
* Requires for pico container when no {@link BuiltInQualityProfilesDefinition} is defined at all
*/
public BuiltInQProfileRepositoryImpl(Languages languages) {
this(languages, new BuiltInQualityProfilesDefinition[0]);
public BuiltInQProfileRepositoryImpl(DbClient dbClient, Languages languages) {
this(dbClient, languages, new BuiltInQualityProfilesDefinition[0]);
}

public BuiltInQProfileRepositoryImpl(Languages languages, BuiltInQualityProfilesDefinition... definitions) {
public BuiltInQProfileRepositoryImpl(DbClient dbClient, Languages languages, BuiltInQualityProfilesDefinition... definitions) {
this.dbClient = dbClient;
this.languages = languages;
this.definitions = ImmutableList.copyOf(definitions);
}
@@ -98,18 +105,29 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository
return profilesByLanguageAndName;
}

private static List<BuiltInQProfile> toFlatList(Map<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguage) {
Map<String, List<BuiltInQProfile.Builder>> buildersByLanguage = rulesProfilesByLanguage
.entrySet()
.stream()
.collect(MoreCollectors.uniqueIndex(Map.Entry::getKey, BuiltInQProfileRepositoryImpl::toQualityProfileBuilders));
return buildersByLanguage
.entrySet()
.stream()
.filter(BuiltInQProfileRepositoryImpl::ensureAtMostOneDeclaredDefault)
.map(entry -> toQualityProfiles(entry.getValue()))
.flatMap(Collection::stream)
.collect(MoreCollectors.toList());
private List<BuiltInQProfile> toFlatList(Map<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguage) {
if (rulesProfilesByLanguage.isEmpty()) {
return Collections.emptyList();
}

try (DbSession dbSession = dbClient.openSession(false)) {
Map<RuleKey, RuleDefinitionDto> rulesByRuleKey = dbClient.ruleDao().selectAllDefinitions(dbSession)
.stream()
.collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getKey));
Map<String, List<BuiltInQProfile.Builder>> buildersByLanguage = rulesProfilesByLanguage
.entrySet()
.stream()
.collect(MoreCollectors.uniqueIndex(
Map.Entry::getKey,
rulesProfilesByLanguageAndName -> toQualityProfileBuilders(rulesProfilesByLanguageAndName, rulesByRuleKey)));
return buildersByLanguage
.entrySet()
.stream()
.filter(BuiltInQProfileRepositoryImpl::ensureAtMostOneDeclaredDefault)
.map(entry -> toQualityProfiles(entry.getValue()))
.flatMap(Collection::stream)
.collect(MoreCollectors.toList());
}
}

/**
@@ -124,14 +142,15 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository
* RulesProfile with a given name</li>
* </ul>
*/
private static List<BuiltInQProfile.Builder> toQualityProfileBuilders(Map.Entry<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguageAndName) {
private static List<BuiltInQProfile.Builder> toQualityProfileBuilders(Map.Entry<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguageAndName,
Map<RuleKey, RuleDefinitionDto> rulesByRuleKey) {
String language = rulesProfilesByLanguageAndName.getKey();
// use a LinkedHashMap to keep order of insertion of RulesProfiles
Map<String, BuiltInQProfile.Builder> qualityProfileBuildersByName = new LinkedHashMap<>();
for (BuiltInQualityProfile builtInProfile : rulesProfilesByLanguageAndName.getValue().values()) {
qualityProfileBuildersByName.compute(
builtInProfile.name(),
(name, existingBuilder) -> updateOrCreateBuilder(language, existingBuilder, builtInProfile));
(name, existingBuilder) -> updateOrCreateBuilder(language, existingBuilder, builtInProfile, rulesByRuleKey));
}
return ImmutableList.copyOf(qualityProfileBuildersByName.values());
}
@@ -148,16 +167,26 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository
return true;
}

private static BuiltInQProfile.Builder updateOrCreateBuilder(String language, @Nullable BuiltInQProfile.Builder existingBuilder, BuiltInQualityProfile builtInProfile) {
BuiltInQProfile.Builder builder = existingBuilder;
if (builder == null) {
builder = new BuiltInQProfile.Builder()
private static BuiltInQProfile.Builder updateOrCreateBuilder(String language, @Nullable BuiltInQProfile.Builder existingBuilder, BuiltInQualityProfile builtInProfile,
Map<RuleKey, RuleDefinitionDto> rulesByRuleKey) {
BuiltInQProfile.Builder builder = createOrReuseBuilder(existingBuilder, language, builtInProfile);
builder.setDeclaredDefault(builtInProfile.isDefault());
builtInProfile.rules().forEach(builtInActiveRule -> {
RuleKey ruleKey = RuleKey.of(builtInActiveRule.repoKey(), builtInActiveRule.ruleKey());
RuleDefinitionDto ruleDefinition = rulesByRuleKey.get(ruleKey);
checkState(ruleDefinition != null, "Rule with key '%s' not found", ruleKey);
builder.addRule(builtInActiveRule, ruleDefinition.getId());
});
return builder;
}

private static BuiltInQProfile.Builder createOrReuseBuilder(@Nullable BuiltInQProfile.Builder existingBuilder, String language, BuiltInQualityProfile builtInProfile) {
if (existingBuilder == null) {
return new BuiltInQProfile.Builder()
.setLanguage(language)
.setName(builtInProfile.name());
}
return builder
.setDeclaredDefault(builtInProfile.isDefault())
.addRules(builtInProfile.rules());
return existingBuilder;
}

private static List<BuiltInQProfile> toQualityProfiles(List<BuiltInQProfile.Builder> builders) {

+ 6
- 11
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImpl.java View File

@@ -27,13 +27,11 @@ import java.util.Set;
import java.util.stream.Stream;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInActiveRule;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.qualityprofile.ActiveRuleDto;
import org.sonar.db.qualityprofile.RulesProfileDto;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;

import static org.sonar.core.util.stream.MoreCollectors.toSet;
@@ -59,13 +57,13 @@ public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate {

Set<RuleKey> ruleKeys = Stream.concat(
deactivatedKeys.stream(),
builtIn.getActiveRules().stream().map(ar -> RuleKey.of(ar.repoKey(), ar.ruleKey())))
builtIn.getActiveRules().stream().map(BuiltInQProfile.ActiveRule::getRuleKey))
.collect(toSet());
RuleActivationContext context = ruleActivator.createContextForBuiltInProfile(dbSession, rulesProfile, ruleKeys);

Collection<RuleActivation> activations = new ArrayList<>();
for (BuiltInActiveRule ar : builtIn.getActiveRules()) {
RuleActivation activation = convert(ar, context);
for (BuiltInQProfile.ActiveRule ar : builtIn.getActiveRules()) {
RuleActivation activation = convert(ar);
activations.add(activation);
deactivatedKeys.remove(activation.getRuleKey());
}
@@ -82,13 +80,10 @@ public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate {
return changes;
}

private static RuleActivation convert(BuiltInActiveRule ar, RuleActivationContext context) {
RuleKey ruleKey = RuleKey.of(ar.repoKey(), ar.ruleKey());
context.reset(ruleKey);
RuleDefinitionDto ruleDefinition = context.getRule().get();
Map<String, String> params = ar.overriddenParams().stream()
private static RuleActivation convert(BuiltInQProfile.ActiveRule ar) {
Map<String, String> params = ar.getBuiltIn().overriddenParams().stream()
.collect(MoreCollectors.uniqueIndex(BuiltInQualityProfilesDefinition.OverriddenParam::key, BuiltInQualityProfilesDefinition.OverriddenParam::overriddenValue));
return RuleActivation.create(ruleDefinition.getId(), ruleKey, ar.overriddenSeverity(), params);
return RuleActivation.create(ar.getRuleId(), ar.getRuleKey(), ar.getBuiltIn().overriddenSeverity(), params);
}

}

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImplTest.java View File

@@ -108,7 +108,7 @@ public class BuiltInQProfileInsertImplTest {
newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR);
newQp.done();

BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"));
BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"), rule1, rule2);
call(builtIn);

verifyTableSize("rules_profiles", 1);

+ 19
- 11
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImplTest.java View File

@@ -28,11 +28,15 @@ import org.junit.rules.ExpectedException;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.server.language.LanguageTesting;

import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple;
import static org.mockito.Mockito.mock;

public class BuiltInQProfileRepositoryImplTest {
private static final Language FOO_LANGUAGE = LanguageTesting.newLanguage("foo", "foo", "foo");
@@ -40,10 +44,14 @@ public class BuiltInQProfileRepositoryImplTest {

@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);

private DbClient dbClient = dbTester.getDbClient();

@Test
public void get_throws_ISE_if_called_before_initialize() {
BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(new Languages());
BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages());

expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("initialize must be called first");
@@ -53,7 +61,7 @@ public class BuiltInQProfileRepositoryImplTest {

@Test
public void initialize_throws_ISE_if_called_twice() {
BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(new Languages());
BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages());
underTest.initialize();

expectedException.expect(IllegalStateException.class);
@@ -64,7 +72,7 @@ public class BuiltInQProfileRepositoryImplTest {

@Test
public void initialize_creates_no_BuiltInQProfile_when_there_is_no_definition() {
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE));
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages(FOO_LANGUAGE));

underTest.initialize();

@@ -73,7 +81,7 @@ public class BuiltInQProfileRepositoryImplTest {

@Test
public void initialize_creates_no_BuiltInQProfile_when_all_definitions_apply_to_non_defined_languages() {
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(), new DummyProfileDefinition("foo", "P1", false));
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages(), new DummyProfileDefinition("foo", "P1", false));

underTest.initialize();

@@ -82,7 +90,7 @@ public class BuiltInQProfileRepositoryImplTest {

@Test
public void initialize_makes_single_profile_of_a_language_default_even_if_not_flagged_as_so() {
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", false));
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", false));

underTest.initialize();

@@ -93,7 +101,7 @@ public class BuiltInQProfileRepositoryImplTest {

@Test
public void initialize_makes_single_profile_of_a_language_default_even_if_flagged_as_so() {
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", true));
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", true));

underTest.initialize();

@@ -109,7 +117,7 @@ public class BuiltInQProfileRepositoryImplTest {
Collections.shuffle(definitions);
String firstName = definitions.get(0).getName();
String secondName = definitions.get(1).getName();
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), definitions.toArray(new BuiltInQualityProfilesDefinition[0]));
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), definitions.toArray(new BuiltInQualityProfilesDefinition[0]));

underTest.initialize();

@@ -120,7 +128,7 @@ public class BuiltInQProfileRepositoryImplTest {

@Test
public void initialize_fails_with_ISE_when_two_profiles_with_different_name_are_default_for_the_same_language() {
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE),
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE),
new DummyProfileDefinition("foo", "foo1", true), new DummyProfileDefinition("foo", "foo2", true));

expectedException.expect(IllegalStateException.class);
@@ -132,7 +140,7 @@ public class BuiltInQProfileRepositoryImplTest {
@Test
public void initialize_creates_profile_Sonar_Way_as_default_if_none_other_is_defined_default_for_a_given_language() {
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
new Languages(FOO_LANGUAGE),
dbClient, new Languages(FOO_LANGUAGE),
new DummyProfileDefinition("foo", "doh", false), new DummyProfileDefinition("foo", "boo", false),
new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", false));

@@ -148,7 +156,7 @@ public class BuiltInQProfileRepositoryImplTest {
@Test
public void initialize_does_not_create_Sonar_Way_as_default_if_other_profile_is_defined_as_default() {
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
new Languages(FOO_LANGUAGE),
dbClient, new Languages(FOO_LANGUAGE),
new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", true));

underTest.initialize();
@@ -164,7 +172,7 @@ public class BuiltInQProfileRepositoryImplTest {
public void initialize_matches_Sonar_Way_default_with_case_sensitivity() {
String sonarWayInOtherCase = SONAR_WAY_QP_NAME.toUpperCase();
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
new Languages(FOO_LANGUAGE),
dbClient, new Languages(FOO_LANGUAGE),
new DummyProfileDefinition("foo", "goo", false), new DummyProfileDefinition("foo", sonarWayInOtherCase, false));

underTest.initialize();

+ 27
- 10
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryRule.java View File

@@ -19,13 +19,18 @@
*/
package org.sonar.server.qualityprofile;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.junit.rules.ExternalResource;
import org.sonar.api.resources.Language;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.rule.RuleDefinitionDto;

import static com.google.common.base.Preconditions.checkState;

@@ -60,27 +65,39 @@ public class BuiltInQProfileRepositoryRule extends ExternalResource implements B
return add(language, profileName, false);
}

public BuiltInQProfile add(Language language, String profileName, boolean isDefault, BuiltInQualityProfilesDefinition.BuiltInActiveRule... rules) {
public BuiltInQProfile add(Language language, String profileName, boolean isDefault) {
return add(language, profileName, isDefault, new BuiltInQProfile.ActiveRule[0]);
}

public BuiltInQProfile add(Language language, String profileName, boolean isDefault, BuiltInQProfile.ActiveRule... rules) {
BuiltInQProfile builtIn = create(language, profileName, isDefault, rules);
profiles.add(builtIn);
return builtIn;
}

public BuiltInQProfile create(Language language, String profileName, boolean isDefault, BuiltInQualityProfilesDefinition.BuiltInActiveRule... rules) {
return new BuiltInQProfile.Builder()
public BuiltInQProfile create(Language language, String profileName, boolean isDefault, BuiltInQProfile.ActiveRule... rules) {
BuiltInQProfile.Builder builder = new BuiltInQProfile.Builder()
.setLanguage(language.getKey())
.setName(profileName)
.setDeclaredDefault(isDefault)
.addRules(Arrays.asList(rules))
.build();
.setDeclaredDefault(isDefault);
Arrays.stream(rules).forEach(builder::addRule);
return builder.build();
}

public BuiltInQProfile create(BuiltInQualityProfilesDefinition.BuiltInQualityProfile api) {
return new BuiltInQProfile.Builder()
public BuiltInQProfile create(BuiltInQualityProfilesDefinition.BuiltInQualityProfile api, RuleDefinitionDto... rules) {
BuiltInQProfile.Builder builder = new BuiltInQProfile.Builder()
.setLanguage(api.language())
.setName(api.name())
.setDeclaredDefault(api.isDefault())
.addRules(new ArrayList<>(api.rules()))
.setDeclaredDefault(api.isDefault());
Map<RuleKey, RuleDefinitionDto> rulesByRuleKey = Arrays.stream(rules)
.collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getKey));
api.rules().forEach(rule -> {
RuleKey ruleKey = RuleKey.of(rule.repoKey(), rule.ruleKey());
RuleDefinitionDto ruleDefinition = rulesByRuleKey.get(ruleKey);
Preconditions.checkState(ruleDefinition != null, "Rule '%s' not found", ruleKey);
builder.addRule(rule, ruleDefinition.getId());
});
return builder
.build();
}
}

+ 5
- 5
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java View File

@@ -87,7 +87,7 @@ public class BuiltInQProfileUpdateImplTest {
newQp.activateRule(rule1.getRepositoryKey(), rule1.getRuleKey()).overrideSeverity(Severity.CRITICAL);
newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR);
newQp.done();
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"));
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule1, rule2);

underTest.update(db.getSession(), builtIn, persistedProfile);

@@ -105,7 +105,7 @@ public class BuiltInQProfileUpdateImplTest {
NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()).overrideSeverity(Severity.CRITICAL);
newQp.done();
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"));
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule);

activateRuleInDb(persistedProfile, rule, BLOCKER);

@@ -124,7 +124,7 @@ public class BuiltInQProfileUpdateImplTest {
NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()).overrideSeverity(Severity.CRITICAL);
newQp.done();
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"));
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule);

activateRuleInDb(persistedProfile, rule, CRITICAL);

@@ -144,7 +144,7 @@ public class BuiltInQProfileUpdateImplTest {
NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR);
newQp.done();
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"));
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule1, rule2);

// built-in definition contains only rule2
// so rule1 must be deactivated
@@ -169,7 +169,7 @@ public class BuiltInQProfileUpdateImplTest {
newQp.activateRule(rule1.getRepositoryKey(), rule1.getRuleKey()).overrideSeverity(Severity.CRITICAL);
newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR);
newQp.done();
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"));
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule1, rule2);

// rule1 must be updated (blocker to critical)
// rule2 must be activated

+ 22
- 4
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesNotificationTest.java View File

@@ -22,12 +22,15 @@ package org.sonar.server.qualityprofile;
import com.google.common.collect.Multimap;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Consumer;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
@@ -36,6 +39,7 @@ import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQ
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.LogTester;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.organization.OrganizationDto;
@@ -48,6 +52,7 @@ import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.util.TypeValidations;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Collections.singleton;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.apache.commons.lang.math.RandomUtils.nextLong;
@@ -303,8 +308,21 @@ public class RegisterQualityProfilesNotificationTest {

Arrays.stream(dbRules).forEach(dbRule -> newQp.activateRule(dbRule.getRepositoryKey(), dbRule.getRuleKey()).overrideSeverity(Severity.MAJOR));
newQp.done();
builtInQProfileRepositoryRule.add(newLanguage(dbProfile.getLanguage()), dbProfile.getName(), false,
context.profile(dbProfile.getLanguage(), dbProfile.getName()).rules().toArray(new BuiltInActiveRule[0]));
List<BuiltInActiveRule> rules = context.profile(dbProfile.getLanguage(), dbProfile.getName()).rules();
BuiltInQProfile.ActiveRule[] activeRules = toActiveRules(rules, dbRules);
builtInQProfileRepositoryRule.add(newLanguage(dbProfile.getLanguage()), dbProfile.getName(), false, activeRules);
}

private static BuiltInQProfile.ActiveRule[] toActiveRules(List<BuiltInActiveRule> rules, RuleDefinitionDto[] dbRules) {
Map<RuleKey, RuleDefinitionDto> dbRulesByRuleKey = Arrays.stream(dbRules)
.collect(MoreCollectors.uniqueIndex(RuleDefinitionDto::getKey));
return rules.stream()
.map(r -> {
RuleKey ruleKey = RuleKey.of(r.repoKey(), r.ruleKey());
RuleDefinitionDto ruleDefinitionDto = dbRulesByRuleKey.get(ruleKey);
checkState(ruleDefinitionDto != null, "Rule '%s' not found", ruleKey);
return new BuiltInQProfile.ActiveRule(ruleDefinitionDto.getId(), r);
}).toArray(BuiltInQProfile.ActiveRule[]::new);
}

private void addPluginProfile(QProfileDto profile, RuleDefinitionDto... dbRules) {
@@ -313,8 +331,8 @@ public class RegisterQualityProfilesNotificationTest {

Arrays.stream(dbRules).forEach(dbRule -> newQp.activateRule(dbRule.getRepositoryKey(), dbRule.getRuleKey()).overrideSeverity(Severity.MAJOR));
newQp.done();
builtInQProfileRepositoryRule.add(newLanguage(profile.getLanguage()), profile.getName(), false,
context.profile(profile.getLanguage(), profile.getName()).rules().toArray(new BuiltInActiveRule[0]));
BuiltInQProfile.ActiveRule[] activeRules = toActiveRules(context.profile(profile.getLanguage(), profile.getName()).rules(), dbRules);
builtInQProfileRepositoryRule.add(newLanguage(profile.getLanguage()), profile.getName(), false, activeRules);
}

private RulesProfileDto insertBuiltInProfile(String language) {

Loading…
Cancel
Save