import org.sonar.xoo.rule.Xoo2BasicProfile;
import org.sonar.xoo.rule.Xoo2SonarWayProfile;
import org.sonar.xoo.rule.XooBasicProfile;
+import org.sonar.xoo.rule.XooBuiltInQualityProfilesDefinition;
import org.sonar.xoo.rule.XooEmptyProfile;
import org.sonar.xoo.rule.XooFakeExporter;
import org.sonar.xoo.rule.XooFakeImporter;
if (context.getSonarQubeVersion().isGreaterThanOrEqual(Version.create(5, 5))) {
context.addExtension(CpdTokenizerSensor.class);
}
+ if (context.getSonarQubeVersion().isGreaterThanOrEqual(Version.create(6,6))) {
+ context.addExtension(XooBuiltInQualityProfilesDefinition.class);
+ }
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.xoo.rule;
+
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
+import org.sonar.xoo.Xoo;
+
+import static org.sonar.xoo.rule.XooRulesDefinition.XOO_REPOSITORY;
+
+public class XooBuiltInQualityProfilesDefinition implements BuiltInQualityProfilesDefinition {
+ @Override
+ public void define(Context context) {
+ NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile("test BuiltInQualityProfilesDefinition", Xoo.KEY);
+ profile.setDefault(false);
+ NewBuiltInActiveRule rule = profile.activateRule(XOO_REPOSITORY, HasTagSensor.RULE_KEY);
+ rule.overrideSeverity("BLOCKER");
+ rule.overrideParam("tag", "TODO");
+ profile.done();
+ }
+}
new XooPlugin().define(context);
assertThat(context.getExtensions()).hasSize(49).contains(CpdTokenizerSensor.class);
}
+
+ @Test
+ public void provide_extensions_for_6_6() {
+ SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.parse("6.6"), SonarQubeSide.SCANNER);
+ Plugin.Context context = new Plugin.Context(runtime);
+ new XooPlugin().define(context);
+ assertThat(context.getExtensions()).hasSize(50).contains(CpdTokenizerSensor.class);
+ }
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.xoo.rule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInQualityProfile;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class XooBuiltInQualityProfilesDefinitionTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private XooBuiltInQualityProfilesDefinition underTest = new XooBuiltInQualityProfilesDefinition();
+
+ @Test
+ public void test_built_in_quality_profile() {
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+
+ underTest.define(context);
+
+ BuiltInQualityProfile profile = context.profile("xoo", "test BuiltInQualityProfilesDefinition");
+ assertThat(profile.isDefault()).isFalse();
+ assertThat(profile.name()).isEqualTo("test BuiltInQualityProfilesDefinition");
+ assertThat(profile.language()).isEqualTo("xoo");
+ assertThat(profile.rules()).hasSize(1);
+ BuiltInQualityProfilesDefinition.BuiltInActiveRule activeRule = profile.rule(RuleKey.of("xoo", "HasTag"));
+ assertThat(activeRule.overriddenSeverity()).isEqualTo("BLOCKER");
+ assertThat(activeRule.overriddenParams()).hasSize(1);
+ assertThat(activeRule.overriddenParam("tag").overriddenValue()).isEqualTo("TODO");
+ }
+}
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.rules.AnnotationRuleParser;
import org.sonar.api.rules.XMLRuleParser;
+import org.sonar.api.server.profile.BuiltInQualityProfileAnnotationLoader;
import org.sonar.api.server.rule.RulesDefinitionXmlLoader;
import org.sonar.api.utils.Durations;
import org.sonar.api.utils.System2;
XMLProfileParser.class,
XMLProfileSerializer.class,
AnnotationProfileParser.class,
+ BuiltInQualityProfileAnnotationLoader.class,
Rules.QProfiles.class,
// rule
assertThat(picoContainer.getComponentAdapters())
.hasSize(
CONTAINER_ITSELF
- + 72 // level 4
+ + 73 // level 4
+ 4 // content of CeConfigurationModule
+ 4 // content of CeQueueModule
+ 4 // content of CeHttpModule
import org.sonar.server.property.InternalPropertiesImpl;
import org.sonar.server.property.ws.PropertiesWs;
import org.sonar.server.qualitygate.QualityGateModule;
+import org.sonar.server.qualityprofile.BuiltInQProfileDefinitionsBridge;
import org.sonar.server.qualityprofile.BuiltInQProfileRepositoryImpl;
import org.sonar.server.qualityprofile.QProfileBackuperImpl;
import org.sonar.server.qualityprofile.QProfileComparison;
BillingValidationsProxyImpl.class,
// quality profile
+ BuiltInQProfileDefinitionsBridge.class,
BuiltInQProfileRepositoryImpl.class,
ActiveRuleIndexer.class,
XMLProfileParser.class,
import java.util.ArrayList;
import java.util.List;
import javax.annotation.concurrent.Immutable;
-import org.sonar.api.profiles.ProfileDefinition;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
/**
- * Represent a Quality Profile as computed from {@link ProfileDefinition} provided by installed plugins.
+ * Represent a Quality Profile as computed from {@link BuiltInQualityProfilesDefinition} provided by installed plugins.
*/
@Immutable
public final class BuiltInQProfile {
private final QProfileName qProfileName;
private final boolean isDefault;
- private final List<org.sonar.api.rules.ActiveRule> activeRules;
+ private final List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> activeRules;
private BuiltInQProfile(Builder builder) {
this.qProfileName = new QProfileName(builder.language, builder.name);
return isDefault;
}
- public List<org.sonar.api.rules.ActiveRule> getActiveRules() {
+ public List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> getActiveRules() {
return activeRules;
}
private String name;
private boolean declaredDefault;
private boolean computedDefault;
- private final List<org.sonar.api.rules.ActiveRule> activeRules = new ArrayList<>();
+ private final List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> activeRules = new ArrayList<>();
public Builder setLanguage(String language) {
this.language = language;
return this;
}
- Builder addRules(List<org.sonar.api.rules.ActiveRule> rules) {
+ Builder addRules(List<BuiltInQualityProfilesDefinition.BuiltInActiveRule> rules) {
this.activeRules.addAll(rules);
return this;
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile;
+
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.sonar.api.profiles.ProfileDefinition;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rules.ActiveRuleParam;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
+import org.sonar.api.utils.ValidationMessages;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.api.utils.log.Profiler;
+
+import static java.lang.String.format;
+
+/**
+ * Bridge between deprecated {@link ProfileDefinition} API and new {@link BuiltInQualityProfilesDefinition}
+ */
+public class BuiltInQProfileDefinitionsBridge implements BuiltInQualityProfilesDefinition {
+ private static final Logger LOGGER = Loggers.get(BuiltInQProfileDefinitionsBridge.class);
+
+ private final List<ProfileDefinition> definitions;
+
+ /**
+ * Requires for pico container when no {@link ProfileDefinition} is defined at all
+ */
+ public BuiltInQProfileDefinitionsBridge() {
+ this(new ProfileDefinition[0]);
+ }
+
+ public BuiltInQProfileDefinitionsBridge(ProfileDefinition... definitions) {
+ this.definitions = ImmutableList.copyOf(definitions);
+ }
+
+ @Override
+ public void define(Context context) {
+ Profiler profiler = Profiler.create(Loggers.get(getClass()));
+ for (ProfileDefinition definition : definitions) {
+ profiler.start();
+ ValidationMessages validation = ValidationMessages.create();
+ RulesProfile profile = definition.createProfile(validation);
+ validation.log(LOGGER);
+ if (profile == null) {
+ profiler.stopDebug(format("Loaded definition %s that return no profile", definition));
+ } else {
+ if (!validation.hasErrors()) {
+ define(context, profile);
+ }
+ profiler.stopDebug(format("Loaded deprecated profile definition %s for language %s", profile.getName(), profile.getLanguage()));
+ }
+ }
+ }
+
+ private static void define(Context context, RulesProfile profile) {
+ NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile(profile.getName(), profile.getLanguage())
+ .setDefault(profile.getDefaultProfile().booleanValue());
+
+ for (org.sonar.api.rules.ActiveRule ar : profile.getActiveRules()) {
+ NewBuiltInActiveRule newActiveRule = newQp.activateRule(ar.getRepositoryKey(), ar.getRuleKey());
+ RulePriority overriddenSeverity = ar.getOverriddenSeverity();
+ if (overriddenSeverity != null) {
+ newActiveRule.overrideSeverity(overriddenSeverity.name());
+ }
+ for (ActiveRuleParam param : ar.getActiveRuleParams()) {
+ newActiveRule.overrideParam(param.getKey(), param.getValue());
+ }
+ }
+ newQp.done();
+ }
+
+}
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.ActiveRuleParam;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
import org.sonar.api.server.rule.RuleParamType;
import org.sonar.api.utils.System2;
import org.sonar.core.util.UuidFactory;
return dto;
}
- private ActiveRuleChange insertActiveRule(DbSession dbSession, RulesProfileDto rulesProfileDto, org.sonar.api.rules.ActiveRule activeRule, long now) {
- RuleKey ruleKey = RuleKey.of(activeRule.getRepositoryKey(), activeRule.getRuleKey());
+ private ActiveRuleChange insertActiveRule(DbSession dbSession, RulesProfileDto rulesProfileDto, BuiltInQualityProfilesDefinition.BuiltInActiveRule activeRule, long now) {
+ RuleKey ruleKey = RuleKey.of(activeRule.repoKey(), activeRule.ruleKey());
RuleDefinitionDto ruleDefinitionDto = ruleRepository.getDefinition(ruleKey)
.orElseThrow(() -> new IllegalStateException("RuleDefinition not found for key " + ruleKey));
dto.setProfileId(rulesProfileDto.getId());
dto.setRuleId(ruleDefinitionDto.getId());
dto.setKey(ActiveRuleKey.of(rulesProfileDto, ruleDefinitionDto.getKey()));
- dto.setSeverity(firstNonNull(activeRule.getSeverity().name(), ruleDefinitionDto.getSeverityString()));
+ dto.setSeverity(firstNonNull(activeRule.overriddenSeverity(), ruleDefinitionDto.getSeverityString()));
dto.setUpdatedAt(now);
dto.setCreatedAt(now);
dbClient.activeRuleDao().insert(dbSession, dto);
return change;
}
- private List<ActiveRuleParamDto> insertActiveRuleParams(DbSession session, org.sonar.api.rules.ActiveRule activeRule, RuleKey ruleKey, ActiveRuleDto activeRuleDto) {
- Map<String, String> valuesByParamKey = activeRule.getActiveRuleParams()
+ private List<ActiveRuleParamDto> insertActiveRuleParams(DbSession session, BuiltInQualityProfilesDefinition.BuiltInActiveRule activeRule, RuleKey ruleKey,
+ ActiveRuleDto activeRuleDto) {
+ Map<String, String> valuesByParamKey = activeRule.overriddenParams()
.stream()
- .collect(MoreCollectors.uniqueIndex(ActiveRuleParam::getParamKey, ActiveRuleParam::getValue));
+ .collect(MoreCollectors.uniqueIndex(BuiltInQualityProfilesDefinition.OverriddenParam::key, BuiltInQualityProfilesDefinition.OverriddenParam::overriddenValue));
return ruleRepository.getRuleParams(ruleKey)
.stream()
.map(param -> {
*/
package org.sonar.server.qualityprofile;
-import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Multimaps;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
-import org.sonar.api.profiles.ProfileDefinition;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Languages;
-import org.sonar.api.utils.ValidationMessages;
+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 static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-import static org.apache.commons.lang.StringUtils.isNotEmpty;
-import static org.apache.commons.lang.StringUtils.lowerCase;
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 Languages languages;
- private final List<ProfileDefinition> definitions;
+ private final List<BuiltInQualityProfilesDefinition> definitions;
private List<BuiltInQProfile> qProfiles;
/**
- * Requires for pico container when no {@link ProfileDefinition} is defined at all
+ * Requires for pico container when no {@link BuiltInQualityProfilesDefinition} is defined at all
*/
public BuiltInQProfileRepositoryImpl(Languages languages) {
- this(languages, new ProfileDefinition[0]);
+ this(languages, new BuiltInQualityProfilesDefinition[0]);
}
- public BuiltInQProfileRepositoryImpl(Languages languages, ProfileDefinition... definitions) {
+ public BuiltInQProfileRepositoryImpl(Languages languages, BuiltInQualityProfilesDefinition... definitions) {
this.languages = languages;
this.definitions = ImmutableList.copyOf(definitions);
}
public void initialize() {
checkState(qProfiles == null, "initialize must be called only once");
- Profiler profiler = Profiler.create(Loggers.get(getClass())).startInfo("Load quality profiles");
- ListMultimap<String, RulesProfile> rulesProfilesByLanguage = buildRulesProfilesByLanguage();
- validateAndClean(rulesProfilesByLanguage);
+ Profiler profiler = Profiler.create(LOGGER).startInfo("Load quality profiles");
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ for (BuiltInQualityProfilesDefinition definition : definitions) {
+ definition.define(context);
+ }
+ Map<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguage = validateAndClean(context);
this.qProfiles = toFlatList(rulesProfilesByLanguage);
profiler.stopDebug();
}
return qProfiles;
}
- /**
- * @return profiles by language
- */
- private ListMultimap<String, RulesProfile> buildRulesProfilesByLanguage() {
- ListMultimap<String, RulesProfile> byLang = ArrayListMultimap.create();
- Profiler profiler = Profiler.create(Loggers.get(getClass()));
- for (ProfileDefinition definition : definitions) {
- profiler.start();
- ValidationMessages validation = ValidationMessages.create();
- RulesProfile profile = definition.createProfile(validation);
- validation.log(LOGGER);
- if (profile == null) {
- profiler.stopDebug(format("Loaded definition %s that return no profile", definition));
- } else {
- if (!validation.hasErrors()) {
- checkArgument(isNotEmpty(profile.getName()), "Profile created by Definition %s can't have a blank name", definition);
- byLang.put(lowerCase(profile.getLanguage(), Locale.ENGLISH), profile);
- }
- profiler.stopDebug(format("Loaded definition %s for language %s", profile.getName(), profile.getLanguage()));
- }
- }
- return byLang;
- }
-
- private void validateAndClean(ListMultimap<String, RulesProfile> byLang) {
- byLang.asMap().entrySet()
+ private Map<String, Map<String, BuiltInQualityProfile>> validateAndClean(BuiltInQualityProfilesDefinition.Context context) {
+ Map<String, Map<String, BuiltInQualityProfile>> profilesByLanguageAndName = context.profilesByLanguageAndName();
+ profilesByLanguageAndName.entrySet()
.removeIf(entry -> {
String language = entry.getKey();
if (languages.get(language) == null) {
LOGGER.info("Language {} is not installed, related Quality profiles are ignored", language);
return true;
}
- Collection<RulesProfile> profiles = entry.getValue();
+ Collection<BuiltInQualityProfile> profiles = entry.getValue().values();
if (profiles.isEmpty()) {
LOGGER.warn("No Quality profiles defined for language: {}", language);
return true;
}
return false;
});
+ return profilesByLanguageAndName;
}
- private static List<BuiltInQProfile> toFlatList(ListMultimap<String, RulesProfile> rulesProfilesByLanguage) {
- Map<String, List<BuiltInQProfile.Builder>> buildersByLanguage = Multimaps.asMap(rulesProfilesByLanguage)
+ 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));
* RulesProfile with a given name</li>
* </ul>
*/
- private static List<BuiltInQProfile.Builder> toQualityProfileBuilders(Map.Entry<String, List<RulesProfile>> rulesProfilesByLanguage) {
- String language = rulesProfilesByLanguage.getKey();
+ private static List<BuiltInQProfile.Builder> toQualityProfileBuilders(Map.Entry<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguageAndName) {
+ String language = rulesProfilesByLanguageAndName.getKey();
// use a LinkedHashMap to keep order of insertion of RulesProfiles
Map<String, BuiltInQProfile.Builder> qualityProfileBuildersByName = new LinkedHashMap<>();
- for (RulesProfile rulesProfile : rulesProfilesByLanguage.getValue()) {
+ for (BuiltInQualityProfile builtInProfile : rulesProfilesByLanguageAndName.getValue().values()) {
qualityProfileBuildersByName.compute(
- rulesProfile.getName(),
- (name, existingBuilder) -> updateOrCreateBuilder(language, existingBuilder, rulesProfile));
+ builtInProfile.name(),
+ (name, existingBuilder) -> updateOrCreateBuilder(language, existingBuilder, builtInProfile));
}
return ImmutableList.copyOf(qualityProfileBuildersByName.values());
}
return true;
}
- private static BuiltInQProfile.Builder updateOrCreateBuilder(String language, @Nullable BuiltInQProfile.Builder existingBuilder, RulesProfile rulesProfile) {
+ private static BuiltInQProfile.Builder updateOrCreateBuilder(String language, @Nullable BuiltInQProfile.Builder existingBuilder, BuiltInQualityProfile builtInProfile) {
BuiltInQProfile.Builder builder = existingBuilder;
if (builder == null) {
builder = new BuiltInQProfile.Builder()
.setLanguage(language)
- .setName(rulesProfile.getName());
+ .setName(builtInProfile.name());
}
- Boolean defaultProfile = rulesProfile.getDefaultProfile();
- boolean declaredDefault = defaultProfile != null && defaultProfile;
return builder
- // if there is multiple RulesProfiles with the same name, if at least one is declared default,
- // then QualityProfile is flagged as declared default
- .setDeclaredDefault(builder.isDeclaredDefault() || declaredDefault)
- .addRules(rulesProfile.getActiveRules());
+ .setDeclaredDefault(builtInProfile.isDefault())
+ .addRules(builtInProfile.rules());
}
private static List<BuiltInQProfile> toQualityProfiles(List<BuiltInQProfile.Builder> builders) {
import java.util.Map;
import java.util.Set;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.ActiveRuleParam;
+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;
});
// these rules are not part of the built-in profile anymore
- toBeDeactivated.forEach(ruleKey ->
- changes.addAll(ruleActivator.deactivateOnBuiltInRulesProfile(dbSession, ruleProfile, ruleKey, false)));
+ toBeDeactivated.forEach(ruleKey -> changes.addAll(ruleActivator.deactivateOnBuiltInRulesProfile(dbSession, ruleProfile, ruleKey, false)));
activeRuleIndexer.commitAndIndex(dbSession, changes);
return changes;
}
- private static RuleActivation convert(org.sonar.api.rules.ActiveRule ar) {
- String severity = ar.getSeverity() != null ? ar.getSeverity().name() : null;
- Map<String, String> params = ar.getActiveRuleParams().stream()
- .collect(MoreCollectors.uniqueIndex(ActiveRuleParam::getKey, ActiveRuleParam::getValue));
- return RuleActivation.create(ar.getRule().ruleKey(), severity, params);
+ private static RuleActivation convert(BuiltInActiveRule ar) {
+ Map<String, String> params = ar.overriddenParams().stream()
+ .collect(MoreCollectors.uniqueIndex(BuiltInQualityProfilesDefinition.OverriddenParam::key, BuiltInQualityProfilesDefinition.OverriddenParam::overriddenValue));
+ return RuleActivation.create(RuleKey.of(ar.repoKey(), ar.ruleKey()), ar.overriddenSeverity(), params);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile;
+
+import java.util.Arrays;
+import org.junit.Test;
+import org.sonar.api.profiles.ProfileDefinition;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleParam;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInActiveRule;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInQualityProfile;
+import org.sonar.api.utils.ValidationMessages;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
+
+public class BuiltInQProfileDefinitionsBridgeTest {
+
+ @Test
+ public void noProfileDefinitions() {
+ BuiltInQProfileDefinitionsBridge bridge = new BuiltInQProfileDefinitionsBridge();
+
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ bridge.define(context);
+
+ assertThat(context.profilesByLanguageAndName()).isEmpty();
+ }
+
+ @Test
+ public void bridgeProfileDefinitions() {
+ BuiltInQProfileDefinitionsBridge bridge = new BuiltInQProfileDefinitionsBridge(new Profile1(), new NullProfile(), new ProfileWithError());
+
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ bridge.define(context);
+
+ assertThat(context.profilesByLanguageAndName()).hasSize(1);
+ assertThat(context.profilesByLanguageAndName().get("xoo")).hasSize(1);
+
+ BuiltInQualityProfile profile1 = context.profile("xoo", "Profile 1");
+ assertThat(profile1).isNotNull();
+ assertThat(profile1.rules()).hasSize(3);
+ BuiltInActiveRule defaultSeverity = profile1.rule(RuleKey.of("repo1", "defaultSeverity"));
+ assertThat(defaultSeverity).isNotNull();
+ assertThat(defaultSeverity.overriddenSeverity()).isNull();
+ assertThat(defaultSeverity.overriddenParams()).isEmpty();
+
+ assertThat(profile1.rule(RuleKey.of("repo1", "overrideSeverity")).overriddenSeverity()).isEqualTo(Severity.CRITICAL);
+
+ assertThat(profile1.rule(RuleKey.of("repo1", "overrideParam")).overriddenParams())
+ .extracting(BuiltInQualityProfilesDefinition.OverriddenParam::key, BuiltInQualityProfilesDefinition.OverriddenParam::overriddenValue).containsOnly(tuple("param", "value"));
+ }
+
+ private class Profile1 extends ProfileDefinition {
+ @Override
+ public RulesProfile createProfile(ValidationMessages validation) {
+ RulesProfile profile1 = RulesProfile.create("Profile 1", "xoo");
+
+ profile1.activateRule(Rule.create("repo1", "defaultSeverity"), null);
+ profile1.activateRule(Rule.create("repo1", "overrideSeverity"), RulePriority.CRITICAL);
+ Rule ruleWithParam = Rule.create("repo1", "overrideParam");
+ ruleWithParam.setParams(Arrays.asList(new RuleParam(ruleWithParam, "param", "", "")));
+ ActiveRule arWithParam = profile1.activateRule(ruleWithParam, null);
+ arWithParam.setParameter("param", "value");
+
+ return profile1;
+ }
+ }
+
+ private class NullProfile extends ProfileDefinition {
+ @Override
+ public RulesProfile createProfile(ValidationMessages validation) {
+ return null;
+ }
+ }
+
+ private class ProfileWithError extends ProfileDefinition {
+ @Override
+ public RulesProfile createProfile(ValidationMessages validation) {
+ validation.addErrorText("Foo");
+ return RulesProfile.create("Profile with errors", "xoo");
+ }
+ }
+}
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.RulePriority;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
import org.sonar.core.util.SequenceUuidFactory;
import static java.util.Collections.emptyList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
-import static org.sonar.api.rules.RulePriority.CRITICAL;
-import static org.sonar.api.rules.RulePriority.MAJOR;
public class BuiltInQProfileInsertImplTest {
OrganizationDto org = db.organizations().insert();
RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
- RulesProfile apiProfile = RulesProfile.create("the name", "xoo");
- activeRule(apiProfile, rule1, CRITICAL);
- activeRule(apiProfile, rule2, MAJOR);
- BuiltInQProfile builtIn = builtInQProfileRepository.create(apiProfile);
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("the name", "xoo");
+
+ newQp.activateRule(rule1.getRepositoryKey(), rule1.getRuleKey()).overrideSeverity(Severity.CRITICAL);
+ newQp.activateRule(rule2.getRepositoryKey(), rule2.getRuleKey()).overrideSeverity(Severity.MAJOR);
+ newQp.done();
+
+ BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"));
call(builtIn);
verifyTableSize("rules_profiles", 1);
@Test
public void flag_profile_as_default_on_organization_if_declared_as_default_by_api() {
OrganizationDto org = db.organizations().insert();
- RulesProfile apiProfile = RulesProfile.create("the name", "xoo");
- apiProfile.setDefaultProfile(true);
- BuiltInQProfile builtIn = builtInQProfileRepository.create(apiProfile);
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("the name", "xoo").setDefault(true);
+ newQp.done();
+
+ BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"));
call(builtIn);
@Test
public void existing_default_profile_in_organization_must_not_be_changed() {
- RulesProfile apiProfile = RulesProfile.create("the name", "xoo");
- apiProfile.setDefaultProfile(true);
- BuiltInQProfile builtIn = builtInQProfileRepository.create(apiProfile);
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("the name", "xoo").setDefault(true);
+ newQp.done();
+ BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"));
OrganizationDto org = db.organizations().insert();
- QProfileDto currentDefault = db.qualityProfiles().insert(org, p -> p.setLanguage(apiProfile.getLanguage()));
+ QProfileDto currentDefault = db.qualityProfiles().insert(org, p -> p.setLanguage("xoo"));
db.qualityProfiles().setAsDefault(currentDefault);
call(builtIn);
- QProfileDto defaultProfile = db.getDbClient().qualityProfileDao().selectDefaultProfile(dbSession, org, apiProfile.getLanguage());
+ QProfileDto defaultProfile = db.getDbClient().qualityProfileDao().selectDefaultProfile(dbSession, org, "xoo");
assertThat(defaultProfile.getKee()).isEqualTo(currentDefault.getKee());
}
@Test
public void dont_flag_profile_as_default_on_organization_if_not_declared_as_default_by_api() {
OrganizationDto org = db.organizations().insert();
- RulesProfile apiProfile = RulesProfile.create("the name", "xoo");
- apiProfile.setDefaultProfile(false);
- BuiltInQProfile builtIn = builtInQProfileRepository.create(apiProfile);
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("the name", "xoo").setDefault(false);
+ newQp.done();
+ BuiltInQProfile builtIn = builtInQProfileRepository.create(context.profile("xoo", "the name"));
call(builtIn);
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Random;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.api.profiles.ProfileDefinition;
-import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
-import org.sonar.api.utils.ValidationMessages;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
import org.sonar.server.language.LanguageTesting;
import static java.util.Arrays.asList;
assertThat(underTest.get()).isEmpty();
}
- @Test
- public void initialize_throws_IAE_if_profileDefinition_creates_RulesProfile_with_null_name() {
- DummyProfileDefinition definition = new DummyProfileDefinition("foo", null, false);
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(), definition);
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Profile created by Definition " + definition + " can't have a blank name");
-
- underTest.initialize();
- }
-
- @Test
- public void initialize_throws_IAE_if_profileDefinition_creates_RulesProfile_with_empty_name() {
- DummyProfileDefinition definition = new DummyProfileDefinition("foo", "", false);
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(), definition);
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Profile created by Definition " + definition + " can't have a blank name");
-
- underTest.initialize();
- }
-
@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));
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 ProfileDefinition[0]));
+ BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), definitions.toArray(new BuiltInQualityProfilesDefinition[0]));
underTest.initialize();
underTest.initialize();
}
- @Test
- public void initialize_creates_profile_as_default_even_if_only_one_profile_with_given_name_has_default_flag_true() {
- String name = "doh";
- boolean flag = new Random().nextBoolean();
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE),
- new DummyProfileDefinition("foo", name, flag), new DummyProfileDefinition("foo", name, !flag));
-
- underTest.initialize();
-
- assertThat(underTest.get())
- .extracting(BuiltInQProfile::getLanguage, BuiltInQProfile::isDefault)
- .containsExactly(tuple("foo", true));
- }
-
- @Test
- public void initialize_creates_single_profile_if_several_profile_have_the_same_name_for_a_given_language() {
- BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE),
- new DummyProfileDefinition("foo", "aName", true), new DummyProfileDefinition("foo", "aName", true));
-
- underTest.initialize();
-
- assertThat(underTest.get())
- .extracting(BuiltInQProfile::getLanguage, BuiltInQProfile::getName)
- .containsExactlyInAnyOrder(tuple(FOO_LANGUAGE.getKey(), "aName"));
- }
-
@Test
public void initialize_creates_profile_Sonar_Way_as_default_if_none_other_is_defined_default_for_a_given_language() {
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
.containsExactly("goo");
}
- private static final class DummyProfileDefinition extends ProfileDefinition {
+ private static final class DummyProfileDefinition implements BuiltInQualityProfilesDefinition {
private final String language;
private final String name;
private final boolean defaultProfile;
}
@Override
- public RulesProfile createProfile(ValidationMessages validation) {
- RulesProfile res = RulesProfile.create(name, language);
- res.setDefaultProfile(defaultProfile);
- return res;
- }
-
- String getLanguage() {
- return language;
+ public void define(Context context) {
+ context.createBuiltInQualityProfile(name, language)
+ .setDefault(defaultProfile).done();
}
String getName() {
return name;
}
- boolean isDefaultProfile() {
- return defaultProfile;
- }
}
}
import java.util.Arrays;
import java.util.List;
import org.junit.rules.ExternalResource;
-import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Language;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
import static com.google.common.base.Preconditions.checkState;
return add(language, profileName, false);
}
- public BuiltInQProfile add(Language language, String profileName, boolean isDefault, org.sonar.api.rules.ActiveRule... rules) {
+ public BuiltInQProfile add(Language language, String profileName, boolean isDefault, BuiltInQualityProfilesDefinition.BuiltInActiveRule... rules) {
BuiltInQProfile builtIn = create(language, profileName, isDefault, rules);
profiles.add(builtIn);
return builtIn;
}
- public BuiltInQProfile create(Language language, String profileName, boolean isDefault, org.sonar.api.rules.ActiveRule... rules) {
+ public BuiltInQProfile create(Language language, String profileName, boolean isDefault, BuiltInQualityProfilesDefinition.BuiltInActiveRule... rules) {
return new BuiltInQProfile.Builder()
.setLanguage(language.getKey())
.setName(profileName)
.build();
}
- public BuiltInQProfile create(RulesProfile api) {
+ public BuiltInQProfile create(BuiltInQualityProfilesDefinition.BuiltInQualityProfile api) {
return new BuiltInQProfile.Builder()
- .setLanguage(api.getLanguage())
- .setName(api.getName())
- .setDeclaredDefault(api.getDefaultProfile())
- .addRules(new ArrayList<>(api.getActiveRules()))
+ .setLanguage(api.language())
+ .setName(api.name())
+ .setDeclaredDefault(api.isDefault())
+ .addRules(new ArrayList<>(api.rules()))
.build();
}
}
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rule.Severity;
import org.sonar.api.rules.RulePriority;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.internal.TestSystem2;
import org.sonar.db.DbTester;
public void activate_new_rules() {
RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
- RulesProfile apiProfile = RulesProfile.create("Sonar way", "xoo");
- activateRuleInDef(apiProfile, rule1, CRITICAL);
- activateRuleInDef(apiProfile, rule2, MAJOR);
- BuiltInQProfile builtIn = builtInProfileRepository.create(apiProfile);
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
+ 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"));
underTest.update(db.getSession(), builtIn, persistedProfile);
@Test
public void already_activated_rule_is_updated_in_case_of_differences() {
RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo"));
- RulesProfile apiProfile = RulesProfile.create("Sonar way", "xoo");
- activateRuleInDef(apiProfile, rule, CRITICAL);
- BuiltInQProfile builtIn = builtInProfileRepository.create(apiProfile);
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ 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"));
activateRuleInDb(persistedProfile, rule, BLOCKER);
@Test
public void already_activated_rule_is_not_touched_if_no_differences() {
RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo"));
- RulesProfile apiProfile = RulesProfile.create("Sonar way", "xoo");
- activateRuleInDef(apiProfile, rule, CRITICAL);
- BuiltInQProfile builtIn = builtInProfileRepository.create(apiProfile);
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ 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"));
activateRuleInDb(persistedProfile, rule, CRITICAL);
public void deactivate_rule_that_is_not_in_built_in_definition_anymore() {
RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
- RulesProfile apiProfile = RulesProfile.create("Sonar way", "xoo");
- activateRuleInDef(apiProfile, rule2, CRITICAL);
- BuiltInQProfile builtIn = builtInProfileRepository.create(apiProfile);
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ 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"));
// built-in definition contains only rule2
// so rule1 must be deactivated
RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
RuleDefinitionDto rule3 = db.rules().insert(r -> r.setLanguage("xoo"));
- RulesProfile apiProfile = RulesProfile.create("Sonar way", "xoo");
- activateRuleInDef(apiProfile, rule1, CRITICAL);
- activateRuleInDef(apiProfile, rule2, MAJOR);
- BuiltInQProfile builtIn = builtInProfileRepository.create(apiProfile);
+
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile("Sonar way", "xoo");
+ 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"));
// rule1 must be updated (blocker to critical)
// rule2 must be activated
assertThatProfileIsMarkedAsUpdated(persistedProfile);
}
-
private static void assertThatRuleIsNewlyActivated(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule, RulePriority severity) {
ActiveRuleDto activeRule = findRule(activeRules, rule).get();
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor;
-import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.rule.Severity;
-import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.RulePriority;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInActiveRule;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.LogTester;
import org.sonar.core.util.UuidFactoryFast;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
-import static org.sonar.api.rules.Rule.create;
import static org.sonar.api.rules.RulePriority.MAJOR;
import static org.sonar.db.qualityprofile.QualityProfileTesting.newRuleProfileDto;
import static org.sonar.server.language.LanguageTesting.newLanguage;
}
private void addPluginProfile(RulesProfileDto dbProfile, RuleDefinitionDto... dbRules) {
- RulesProfile pluginProfile = RulesProfile.create(dbProfile.getName(), dbProfile.getLanguage());
- Arrays.stream(dbRules).forEach(dbRule -> pluginProfile.activateRule(create(dbRule.getRepositoryKey(), dbRule.getRuleKey()), null));
- builtInQProfileRepositoryRule.add(newLanguage(dbProfile.getLanguage()), dbProfile.getName(), false, pluginProfile.getActiveRules().toArray(new ActiveRule[0]));
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile(dbProfile.getName(), dbProfile.getLanguage());
+
+ 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]));
}
private void addPluginProfile(QProfileDto profile, RuleDefinitionDto... dbRules) {
- RulesProfile pluginProfile = RulesProfile.create(profile.getName(), profile.getLanguage());
- Arrays.stream(dbRules).forEach(dbRule -> pluginProfile.activateRule(create(dbRule.getRepositoryKey(), dbRule.getRuleKey()), null));
- builtInQProfileRepositoryRule.add(newLanguage(profile.getLanguage()), profile.getName(), false, pluginProfile.getActiveRules().toArray(new ActiveRule[0]));
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile(profile.getName(), profile.getLanguage());
+
+ 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]));
}
private RulesProfileDto insertBuiltInProfile(String language) {
import java.util.Collection;
import org.apache.commons.lang.StringUtils;
+import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleAnnotationUtils;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RulePriority;
-import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
+import org.sonar.api.server.profile.BuiltInQualityProfileAnnotationLoader;
import org.sonar.api.utils.ValidationMessages;
import org.sonar.check.BelongsToProfile;
/**
* @since 2.3
+ * @deprecated since 6.6 use {@link BuiltInQualityProfileAnnotationLoader}
*/
@ServerSide
@ComputeEngineSide
+@Deprecated
public final class AnnotationProfileParser {
private final RuleFinder ruleFinder;
import org.sonar.api.ExtensionPoint;
import org.sonar.api.server.ServerSide;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
import org.sonar.api.utils.ValidationMessages;
/**
* The components <code>AnnotationProfileParser</code> and <code>XMLProfileParser</code> can be used to help implementing the method create().
*
* @since 2.3
+ * @deprecated since 6.6 use {@link BuiltInQualityProfilesDefinition}
*/
@ServerSide
@ExtensionPoint
+@Deprecated
public abstract class ProfileDefinition {
public abstract RulesProfile createProfile(ValidationMessages validation);
"The definition of the profile '%s' (language '%s') contains multiple occurrences of the '%s:%s' rule. The plugin which declares this profile should fix this.",
getName(), getLanguage(), rule.getRepositoryKey(), rule.getKey()));
}
- ActiveRule activeRule = new ActiveRule();
- activeRule.setRule(rule);
- activeRule.setRulesProfile(this);
- activeRule.setSeverity(optionalSeverity == null ? rule.getSeverity() : optionalSeverity);
+ ActiveRule activeRule = new ActiveRule(this, rule, optionalSeverity);
activeRules.add(activeRule);
return activeRule;
}
import org.codehaus.staxmate.SMInputFactory;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
+import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RulePriority;
-import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.ValidationMessages;
private Integer id;
private Rule rule;
private RulePriority severity;
+ private RulePriority overriddenSeverity;
private RulesProfile rulesProfile;
private List<ActiveRuleParam> activeRuleParams = new ArrayList<>();
private String inheritance;
@Deprecated
public ActiveRule(RulesProfile profile, Rule rule, RulePriority severity) {
this.rule = rule;
+ this.overriddenSeverity = severity;
if (severity == null && rule != null) {
this.severity = rule.getSeverity();
} else {
return severity;
}
+ /**
+ * For internal use
+ * @since 6.6
+ * @deprecated
+ */
+ @Deprecated
+ public RulePriority getOverriddenSeverity() {
+ return overriddenSeverity;
+ }
+
/**
* @since 2.5
*/
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.server.profile;
+
+import javax.annotation.CheckForNull;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.rules.RuleAnnotationUtils;
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInActiveRule;
+import org.sonar.check.BelongsToProfile;
+
+/**
+ * Read definitions of quality profiles based on the annotation {@link BelongsToProfile} provided by sonar-check-api. It is used
+ * to feed {@link BuiltInQualityProfilesDefinition}.
+ *
+ * @see BuiltInQualityProfilesDefinition
+ * @since 6.6
+ */
+@ServerSide
+public class BuiltInQualityProfileAnnotationLoader {
+
+ public void load(BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile builtInProfile, String repositoryKey, Class... annotatedClasses) {
+ for (Class<?> annotatedClass : annotatedClasses) {
+ loadActiveRule(builtInProfile, repositoryKey, annotatedClass);
+ }
+ }
+
+ @CheckForNull
+ void loadActiveRule(BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile profile, String repositoryKey, Class<?> clazz) {
+ BelongsToProfile belongsToProfile = clazz.getAnnotation(BelongsToProfile.class);
+ if ((belongsToProfile != null) && StringUtils.equals(belongsToProfile.title(), profile.name())) {
+ String ruleKey = RuleAnnotationUtils.getRuleKey(clazz);
+ NewBuiltInActiveRule activeRule = profile.activateRule(repositoryKey, ruleKey);
+ activeRule.overrideSeverity(belongsToProfile.priority().name());
+ }
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.server.profile;
+
+import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.ExtensionPoint;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
+import static java.util.Collections.unmodifiableList;
+import static java.util.Collections.unmodifiableMap;
+import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+
+/**
+ * Define built-in quality profiles which are automatically registered during SonarQube startup.
+ * We no more provide any facility to load profiles from XML file or annotated classes, but it should
+ * be straightforward to implement (adapt code of deprecated {@link org.sonar.api.profiles.AnnotationProfileParser}
+ * or {@link org.sonar.api.profiles.XMLProfileParser} for example).
+ *
+ * @since 6.6
+ */
+@ServerSide
+@ExtensionPoint
+public interface BuiltInQualityProfilesDefinition {
+
+ /**
+ * Instantiated by core but not by plugins, except for their tests.
+ */
+ class Context {
+
+ private final Map<String, Map<String, BuiltInQualityProfile>> profilesByLanguageAndName = new HashMap<>();
+
+ /**
+ * New builder for {@link BuiltInQualityProfile}.
+ * <br>
+ * A plugin can activate rules in a built in quality profile that is defined by another plugin.
+ */
+ public NewBuiltInQualityProfile createBuiltInQualityProfile(String name, String language) {
+ return new NewBuiltInQualityProfileImpl(this, name, language);
+ }
+
+ private void registerProfile(NewBuiltInQualityProfileImpl newProfile) {
+ String language = newProfile.language();
+ String name = newProfile.name();
+ Preconditions.checkArgument(!profilesByLanguageAndName.computeIfAbsent(language, l -> new LinkedHashMap<>()).containsKey(name),
+ "There is already a quality profile with name '%s' for language '%s'", name, language);
+ profilesByLanguageAndName.get(language).put(name, new BuiltInQualityProfileImpl(newProfile));
+ }
+
+ public Map<String, Map<String, BuiltInQualityProfile>> profilesByLanguageAndName() {
+ return profilesByLanguageAndName;
+ }
+
+ public BuiltInQualityProfile profile(String language, String name) {
+ return profilesByLanguageAndName.computeIfAbsent(language, l -> new LinkedHashMap<>()).get(name);
+ }
+ }
+
+ interface NewBuiltInQualityProfile {
+
+ /**
+ * Set whether this is the default profile for the language. The default profile is used when none is explicitly defined when analyzing a project.
+ */
+ NewBuiltInQualityProfile setDefault(boolean value);
+
+ /**
+ * Activate a rule with specified key.
+ *
+ * @throws IllegalArgumentException if rule is already activated in this profile.
+ */
+ NewBuiltInActiveRule activateRule(String repoKey, String ruleKey);
+
+ Collection<NewBuiltInActiveRule> activeRules();
+
+ String language();
+
+ String name();
+
+ boolean isDefault();
+
+ void done();
+ }
+
+ class NewBuiltInQualityProfileImpl implements NewBuiltInQualityProfile {
+ private final Context context;
+ private final String name;
+ private final String language;
+ private boolean isDefault;
+ private final Map<RuleKey, NewBuiltInActiveRule> newActiveRules = new HashMap<>();
+
+ private NewBuiltInQualityProfileImpl(Context context, String name, String language) {
+ this.context = context;
+ this.name = name;
+ this.language = language;
+ }
+
+ @Override
+ public NewBuiltInQualityProfile setDefault(boolean value) {
+ this.isDefault = value;
+ return this;
+ }
+
+ @Override
+ public NewBuiltInActiveRule activateRule(String repoKey, String ruleKey) {
+ RuleKey ruleKeyObj = RuleKey.of(repoKey, ruleKey);
+ checkArgument(!newActiveRules.containsKey(ruleKeyObj), "The rule '%s' is already activated", ruleKeyObj);
+ NewBuiltInActiveRule newActiveRule = new NewBuiltInActiveRule(repoKey, ruleKey);
+ newActiveRules.put(ruleKeyObj, newActiveRule);
+ return newActiveRule;
+ }
+
+ @Override
+ public String language() {
+ return language;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public boolean isDefault() {
+ return isDefault;
+ }
+
+ @Override
+ public Collection<NewBuiltInActiveRule> activeRules() {
+ return newActiveRules.values();
+ }
+
+ @Override
+ public void done() {
+ checkArgument(isNotBlank(name), "Built-In Quality Profile can't have a blank name");
+ checkArgument(isNotBlank(language), "Built-In Quality Profile can't have a blank language");
+
+ context.registerProfile(this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("NewBuiltInQualityProfile{");
+ sb.append("name='").append(name).append('\'');
+ sb.append(", language='").append(language).append('\'');
+ sb.append(", default='").append(isDefault).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+
+ interface BuiltInQualityProfile {
+ String name();
+
+ String language();
+
+ boolean isDefault();
+
+ @CheckForNull
+ BuiltInActiveRule rule(RuleKey ruleKey);
+
+ List<BuiltInActiveRule> rules();
+ }
+
+ @Immutable
+ class BuiltInQualityProfileImpl implements BuiltInQualityProfile {
+
+ private static final Logger LOG = Loggers.get(BuiltInQualityProfilesDefinition.BuiltInQualityProfileImpl.class);
+ private final String language;
+ private final String name;
+ private final boolean isDefault;
+ private final Map<RuleKey, BuiltInActiveRule> activeRulesByKey;
+
+ private BuiltInQualityProfileImpl(NewBuiltInQualityProfileImpl newProfile) {
+ this.name = newProfile.name();
+ this.language = newProfile.language();
+ this.isDefault = newProfile.isDefault();
+
+ Map<RuleKey, BuiltInActiveRule> ruleBuilder = new HashMap<>();
+ for (NewBuiltInActiveRule newActiveRule : newProfile.activeRules()) {
+ ruleBuilder.put(RuleKey.of(newActiveRule.repoKey, newActiveRule.ruleKey), new BuiltInActiveRule(newActiveRule));
+ }
+ this.activeRulesByKey = unmodifiableMap(ruleBuilder);
+ }
+
+ @Override
+ public String language() {
+ return language;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public boolean isDefault() {
+ return isDefault;
+ }
+
+ @Override
+ @CheckForNull
+ public BuiltInActiveRule rule(RuleKey ruleKey) {
+ return activeRulesByKey.get(ruleKey);
+ }
+
+ @Override
+ public List<BuiltInActiveRule> rules() {
+ return unmodifiableList(new ArrayList<>(activeRulesByKey.values()));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ BuiltInQualityProfileImpl that = (BuiltInQualityProfileImpl) o;
+ return language.equals(that.language) && name.equals(that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name.hashCode();
+ result = 31 * result + language.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("BuiltInQualityProfile{");
+ sb.append("name='").append(name).append('\'');
+ sb.append(", language='").append(language).append('\'');
+ sb.append(", default='").append(isDefault).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+
+ class NewBuiltInActiveRule {
+ private final String repoKey;
+ private final String ruleKey;
+ private String overriddenSeverity = null;
+ private final Map<String, NewOverriddenParam> paramsByKey = new HashMap<>();
+
+ private NewBuiltInActiveRule(String repoKey, String ruleKey) {
+ this.repoKey = repoKey;
+ this.ruleKey = ruleKey;
+ }
+
+ public String repoKey() {
+ return this.repoKey;
+ }
+
+ public String ruleKey() {
+ return this.ruleKey;
+ }
+
+ /**
+ * Override default rule severity in this quality profile. By default the active rule will have the default rule severity.
+ * @param severity See {@link Severity} constants.
+ */
+ public NewBuiltInActiveRule overrideSeverity(String severity) {
+ checkArgument(Severity.ALL.contains(severity), "Severity of rule %s is not correct: %s", RuleKey.of(repoKey, ruleKey), severity);
+ this.overriddenSeverity = severity;
+ return this;
+ }
+
+ /**
+ * Create a parameter with given unique key. Max length of key is 128 characters.
+ */
+ public NewOverriddenParam overrideParam(String paramKey, @Nullable String value) {
+ checkArgument(!paramsByKey.containsKey(paramKey), "The parameter '%s' was already overridden on the built in active rule %s", paramKey, this);
+ NewOverriddenParam param = new NewOverriddenParam(paramKey).setOverriddenValue(value);
+ paramsByKey.put(paramKey, param);
+ return param;
+ }
+
+ @CheckForNull
+ public NewOverriddenParam getOverriddenParam(String paramKey) {
+ return paramsByKey.get(paramKey);
+ }
+
+ public Collection<NewOverriddenParam> getOverriddenParams() {
+ return paramsByKey.values();
+ }
+
+ @Override
+ public String toString() {
+ return format("[repository=%s, key=%s]", repoKey, ruleKey);
+ }
+ }
+
+ /**
+ * A rule activated on a built in quality profile.
+ */
+ @Immutable
+ class BuiltInActiveRule {
+ private final String repoKey;
+ private final String ruleKey;
+ private final String overriddenSeverity;
+ private final Map<String, OverriddenParam> overriddenParams;
+
+ private BuiltInActiveRule(NewBuiltInActiveRule newBuiltInActiveRule) {
+ this.repoKey = newBuiltInActiveRule.repoKey();
+ this.ruleKey = newBuiltInActiveRule.ruleKey();
+ this.overriddenSeverity = newBuiltInActiveRule.overriddenSeverity;
+ Map<String, OverriddenParam> paramsBuilder = new HashMap<>();
+ for (NewOverriddenParam newParam : newBuiltInActiveRule.getOverriddenParams()) {
+ paramsBuilder.put(newParam.key, new OverriddenParam(newParam));
+ }
+ this.overriddenParams = Collections.unmodifiableMap(paramsBuilder);
+ }
+
+ public String repoKey() {
+ return repoKey;
+ }
+
+ public String ruleKey() {
+ return ruleKey;
+ }
+
+ @CheckForNull
+ public String overriddenSeverity() {
+ return overriddenSeverity;
+ }
+
+ @CheckForNull
+ public OverriddenParam overriddenParam(String key) {
+ return overriddenParams.get(key);
+ }
+
+ public List<OverriddenParam> overriddenParams() {
+ return unmodifiableList(new ArrayList<>(overriddenParams.values()));
+ }
+
+ @Override
+ public String toString() {
+ return format("[repository=%s, key=%s]", repoKey, ruleKey);
+ }
+ }
+
+ class NewOverriddenParam {
+ private final String key;
+ private String overriddenValue;
+
+ private NewOverriddenParam(String key) {
+ this.key = key;
+ }
+
+ public String key() {
+ return key;
+ }
+
+ /**
+ * Empty default value will be converted to null. Max length is 4000 characters.
+ */
+ public NewOverriddenParam setOverriddenValue(@Nullable String s) {
+ this.overriddenValue = defaultIfEmpty(s, null);
+ return this;
+ }
+ }
+
+ @Immutable
+ class OverriddenParam {
+ private final String key;
+ private final String overriddenValue;
+
+ private OverriddenParam(NewOverriddenParam newOverriddenParam) {
+ this.key = newOverriddenParam.key();
+ this.overriddenValue = newOverriddenParam.overriddenValue;
+ }
+
+ public String key() {
+ return key;
+ }
+
+ @Nullable
+ public String overriddenValue() {
+ return overriddenValue;
+ }
+
+ }
+
+ /**
+ * This method is executed when server is started.
+ */
+ void define(Context context);
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.server.profile;
+
+import javax.annotation.ParametersAreNonnullByDefault;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.server.profile;
+
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile;
+import org.sonar.check.BelongsToProfile;
+import org.sonar.check.Priority;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class BuiltInQualityProfileAnnotationLoaderTest {
+
+ @Test
+ public void shouldParseAnnotatedClasses() {
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ NewBuiltInQualityProfile newProfile = context.createBuiltInQualityProfile("Foo way", "java");
+
+ new BuiltInQualityProfileAnnotationLoader().load(newProfile, "squid", FakeRule.class, RuleNoProfile.class);
+ newProfile.done();
+
+ assertThat(context.profile("java", "Foo way").rule(RuleKey.of("squid", "fake")).overriddenSeverity()).isEqualTo(Severity.BLOCKER);
+ }
+
+ @Test
+ public void shouldParseOnlyWantedProfile() {
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ NewBuiltInQualityProfile newProfile = context.createBuiltInQualityProfile("Foo way", "java");
+
+ new BuiltInQualityProfileAnnotationLoader().load(newProfile, "squid", FakeRule.class, RuleOnOtherProfile.class, RuleNoProfile.class);
+ newProfile.done();
+
+ assertThat(context.profile("java", "Foo way").rule(RuleKey.of("squid", "fake"))).isNotNull();
+ assertThat(context.profile("java", "Foo way").rule(RuleKey.of("squid", "other"))).isNull();
+ }
+}
+
+@BelongsToProfile(title = "Other profile", priority = Priority.BLOCKER)
+@org.sonar.check.Rule(key = "other", priority = Priority.CRITICAL)
+class RuleOnOtherProfile {
+}
+
+@org.sonar.check.Rule(key = "no", priority = Priority.CRITICAL)
+class RuleNoProfile {
+}
+
+@BelongsToProfile(title = "Foo way", priority = Priority.BLOCKER)
+@org.sonar.check.Rule(key = "fake", priority = Priority.CRITICAL)
+class FakeRule {
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.server.profile;
+
+import java.util.Map;
+import java.util.function.Consumer;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInQualityProfile;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInActiveRule;
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
+
+public class BuiltInQualityProfilesDefinitionTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void coverage() {
+ assertThat(new BuiltInQualityProfilesDefinition.Context().profile("Foo", "xoo")).isNull();
+ }
+
+ @Test
+ public void createEmptyProfile() {
+ Map<String, Map<String, BuiltInQualityProfile>> profiles = define(c -> {
+ c.createBuiltInQualityProfile("Foo", "xoo").done();
+ });
+ assertThat(profiles).containsOnlyKeys("xoo");
+ assertThat(profiles.get("xoo")).containsOnlyKeys("Foo");
+ BuiltInQualityProfile profile = profiles.get("xoo").get("Foo");
+ assertThat(profile.name()).isEqualTo("Foo");
+ assertThat(profile.language()).isEqualTo("xoo");
+ assertThat(profile.isDefault()).isFalse();
+ }
+
+ @Test
+ public void sanityCheck() {
+ Map<String, Map<String, BuiltInQualityProfile>> profiles = define(c -> {
+ NewBuiltInQualityProfile profile1 = c.createBuiltInQualityProfile("Foo1", "xoo");
+ NewBuiltInActiveRule rule = profile1.activateRule("repo", "rule");
+ profile1.done();
+ NewBuiltInQualityProfile profile2 = c.createBuiltInQualityProfile("Foo2", "xoo");
+ profile2.done();
+ NewBuiltInQualityProfile profile3 = c.createBuiltInQualityProfile("Foo1", "xoo2");
+ profile3.done();
+ assertThat(profile1).isEqualTo(profile1);
+ assertThat(profile1).isNotEqualTo(null);
+ assertThat(profile1).isNotEqualTo("Foo");
+ assertThat(profile1).isNotEqualTo(profile2);
+ assertThat(profile1).isNotEqualTo(profile3);
+ assertThat(profile1.hashCode()).isNotEqualTo(profile2.hashCode());
+ assertThat(profile1.toString()).isEqualTo("NewBuiltInQualityProfile{name='Foo1', language='xoo', default='false'}");
+ assertThat(rule.toString()).isEqualTo("[repository=repo, key=rule]");
+ });
+ BuiltInQualityProfile profile1 = profiles.get("xoo").get("Foo1");
+ BuiltInQualityProfile profile2 = profiles.get("xoo").get("Foo2");
+ BuiltInQualityProfile profile3 = profiles.get("xoo2").get("Foo1");
+ assertThat(profile1).isEqualTo(profile1);
+ assertThat(profile1).isNotEqualTo(null);
+ assertThat(profile1).isNotEqualTo("Foo");
+ assertThat(profile1).isNotEqualTo(profile2);
+ assertThat(profile1).isNotEqualTo(profile3);
+ assertThat(profile1.hashCode()).isNotEqualTo(profile2.hashCode());
+ assertThat(profile1.toString()).isEqualTo("BuiltInQualityProfile{name='Foo1', language='xoo', default='false'}");
+ assertThat(profile1.rule(RuleKey.of("repo", "rule")).toString()).isEqualTo("[repository=repo, key=rule]");
+ }
+
+ @Test
+ public void createDefaultProfile() {
+ Map<String, Map<String, BuiltInQualityProfile>> profiles = define(c -> {
+ c.createBuiltInQualityProfile("Foo", "xoo")
+ .setDefault(true)
+ .done();
+ });
+ assertThat(profiles).containsOnlyKeys("xoo");
+ assertThat(profiles.get("xoo")).containsOnlyKeys("Foo");
+ BuiltInQualityProfile profile = profiles.get("xoo").get("Foo");
+ assertThat(profile.name()).isEqualTo("Foo");
+ assertThat(profile.language()).isEqualTo("xoo");
+ assertThat(profile.isDefault()).isTrue();
+ }
+
+ @Test
+ public void duplicateProfile() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("There is already a quality profile with name 'Foo' for language 'xoo'");
+ define(c -> {
+ c.createBuiltInQualityProfile("Foo", "xoo").done();
+ c.createBuiltInQualityProfile("Foo", "xoo").done();
+ });
+ }
+
+ @Test
+ public void createProfileWithRules() {
+ Map<String, Map<String, BuiltInQualityProfile>> profiles = define(c -> {
+ NewBuiltInQualityProfile profile = c.createBuiltInQualityProfile("Foo", "xoo");
+ profile.activateRule("repo", "ruleWithoutParam");
+ profile.activateRule("repo", "ruleWithSeverity").overrideSeverity("CRITICAL");
+ profile.activateRule("repo", "ruleWithParam").overrideParam("param", "value");
+ profile.done();
+ });
+ assertThat(profiles).containsOnlyKeys("xoo");
+ assertThat(profiles.get("xoo")).containsOnlyKeys("Foo");
+ BuiltInQualityProfile profile = profiles.get("xoo").get("Foo");
+ assertThat(profile.name()).isEqualTo("Foo");
+ assertThat(profile.language()).isEqualTo("xoo");
+ assertThat(profile.isDefault()).isFalse();
+ assertThat(profile.rules())
+ .extracting(BuiltInQualityProfilesDefinition.BuiltInActiveRule::repoKey, BuiltInQualityProfilesDefinition.BuiltInActiveRule::ruleKey,
+ BuiltInQualityProfilesDefinition.BuiltInActiveRule::overriddenSeverity, r -> r.overriddenParams().size())
+ .containsOnly(
+ tuple("repo", "ruleWithoutParam", null, 0),
+ tuple("repo", "ruleWithSeverity", "CRITICAL", 0),
+ tuple("repo", "ruleWithParam", null, 1));
+ assertThat(profile.rule(RuleKey.of("repo", "ruleWithParam")).overriddenParam("param").key()).isEqualTo("param");
+ assertThat(profile.rule(RuleKey.of("repo", "ruleWithParam")).overriddenParam("param").overriddenValue()).isEqualTo("value");
+ }
+
+ @Test
+ public void createProfileWithDuplicateRules() {
+
+ define(c -> {
+ NewBuiltInQualityProfile profile = c.createBuiltInQualityProfile("Foo", "xoo");
+ profile.activateRule("repo", "rule");
+
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("The rule 'repo:rule' is already activated");
+
+ profile.activateRule("repo", "rule");
+ });
+ }
+
+ private Map<String, Map<String, BuiltInQualityProfile>> define(Consumer<BuiltInQualityProfilesDefinition.Context> consumer) {
+ BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context();
+ new FakeProfile(consumer).define(context);
+ return context.profilesByLanguageAndName();
+ }
+
+ private class FakeProfile implements BuiltInQualityProfilesDefinition {
+
+ private Consumer<Context> consumer;
+
+ public FakeProfile(Consumer<Context> consumer) {
+ this.consumer = consumer;
+ }
+
+ @Override
+ public void define(Context context) {
+ consumer.accept(context);
+ }
+
+ }
+
+}
RulesDefinition.Context context = new RulesDefinition.Context();
RulesDefinition.NewRepository newRepository = context.createRepository("squid", "java");
NewRule newRule = annotationLoader.loadRule(newRepository, RuleWithProperty.class);
- newRule.setName("Overriden name");
+ newRule.setName("Overridden name");
newRule.param("property").setDefaultValue("true");
- newRule.param("property").setDescription("Overriden");
+ newRule.param("property").setDescription("Overridden");
newRepository.done();
RulesDefinition.Repository repository = context.repository("squid");
RulesDefinition.Rule rule = repository.rules().get(0);
assertThat(rule.key()).isEqualTo("foo");
assertThat(rule.status()).isEqualTo(RuleStatus.BETA);
- assertThat(rule.name()).isEqualTo("Overriden name");
+ assertThat(rule.name()).isEqualTo("Overridden name");
assertThat(rule.htmlDescription()).isEqualTo("Foo Bar");
assertThat(rule.severity()).isEqualTo(Severity.BLOCKER);
assertThat(rule.params()).hasSize(1);
RulesDefinition.Param prop = rule.param("property");
assertThat(prop.key()).isEqualTo("property");
- assertThat(prop.description()).isEqualTo("Overriden");
+ assertThat(prop.description()).isEqualTo("Overridden");
assertThat(prop.defaultValue()).isEqualTo("true");
assertThat(prop.type()).isEqualTo(RuleParamType.STRING);
}
@Override
public String severity() {
- Severity overridenSeverity = newIssue.overriddenSeverity();
- return overridenSeverity != null ? overridenSeverity.name() : null;
+ Severity overriddenSeverity = newIssue.overriddenSeverity();
+ return overriddenSeverity != null ? overriddenSeverity.name() : null;
}
@Override
tracked.setCreationDate(new Date(dto.getCreationDate()));
if (dto.getManualSeverity()) {
- // Severity overriden by user
+ // Severity overridden by user
tracked.setSeverity(dto.getSeverity().name());
}
mergeTo.add(tracked);
Issue issue = issues.get(0);
assertThat(issue.ruleKey()).isEqualTo("xoo:MyCustomRule");
assertThat(issue.line()).isEqualTo(2);
- // Overriden in quality profile
+ // Overridden in quality profile
assertThat(issue.severity()).isEqualTo("CRITICAL");
}
}
tuple("Basic", "xoo", true, true),
tuple("Sonar way", "xoo", true, false),
tuple("empty", "xoo", true, false),
+ tuple("test BuiltInQualityProfilesDefinition", "xoo", true, false),
tuple("Basic", "xoo2", true, true),
tuple("Sonar way", "xoo2", true, false));
}
tuple("default-organization", "Basic", "xoo", true, true),
tuple("default-organization", "Sonar way", "xoo", true, false),
tuple("default-organization", "empty", "xoo", true, false),
+ tuple("default-organization", "test BuiltInQualityProfilesDefinition", "xoo", true, false),
tuple("default-organization", "Basic", "xoo2", true, true),
tuple("default-organization", "Sonar way", "xoo2", true, false));
}