aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2014-10-09 15:05:37 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2014-10-09 15:05:37 +0200
commit393f9888e69e209b2755aebaed3709a167399b29 (patch)
treea92d790a9cc7ad42691250de7a4fe4c52346f75b /server
parent03970eafff028da26540ef814619a02168a57618 (diff)
parentb0903c3790a72643840e147501a739604e3083de (diff)
downloadsonarqube-393f9888e69e209b2755aebaed3709a167399b29.tar.gz
sonarqube-393f9888e69e209b2755aebaed3709a167399b29.zip
Fix merge with 4.5
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java16
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigration.java118
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java60
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/design/file_design.html.erb128
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest.java78
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java85
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java58
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute-result.xml31
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute.xml29
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute_when_custom_rule_have_no_parameter-result.xml31
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute_when_custom_rule_have_no_parameter.xml27
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/no_changes.xml25
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/schema.sql40
-rw-r--r--server/sonar-web/src/main/coffee/coding-rules/views/coding-rules-custom-rule-creation-view.coffee6
-rw-r--r--server/sonar-web/src/main/js/widgets/timeline.js14
-rw-r--r--server/sonar-web/src/main/less/style.less11
-rw-r--r--server/sonar-web/src/main/less/ui.less2
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/db/migrate/601_add_missing_custom_rule_parameters.rb30
19 files changed, 658 insertions, 142 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java
index 71a7692b559..f5ef2c46688 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java
@@ -23,18 +23,9 @@ import com.google.common.collect.ImmutableList;
import org.sonar.server.db.migrations.v36.ViolationMigration;
import org.sonar.server.db.migrations.v42.CompleteIssueMessageMigration;
import org.sonar.server.db.migrations.v42.PackageKeysMigration;
-import org.sonar.server.db.migrations.v43.ConvertIssueDebtToMinutesMigration;
-import org.sonar.server.db.migrations.v43.DevelopmentCostMeasuresMigration;
-import org.sonar.server.db.migrations.v43.IssueChangelogMigration;
-import org.sonar.server.db.migrations.v43.NotResolvedIssuesOnRemovedComponentsMigration;
-import org.sonar.server.db.migrations.v43.RequirementMeasuresMigration;
-import org.sonar.server.db.migrations.v43.TechnicalDebtMeasuresMigration;
-import org.sonar.server.db.migrations.v44.ChangeLogMigration;
-import org.sonar.server.db.migrations.v44.ConvertProfileMeasuresMigration;
-import org.sonar.server.db.migrations.v44.FeedQProfileDatesMigration;
-import org.sonar.server.db.migrations.v44.FeedQProfileKeysMigration;
-import org.sonar.server.db.migrations.v44.IssueActionPlanKeyMigration;
-import org.sonar.server.db.migrations.v44.MeasureDataMigration;
+import org.sonar.server.db.migrations.v43.*;
+import org.sonar.server.db.migrations.v44.*;
+import org.sonar.server.db.migrations.v45.AddMissingCustomRuleParametersMigration;
import org.sonar.server.db.migrations.v45.AddMissingRuleParameterDefaultValuesMigration;
import org.sonar.server.db.migrations.v45.DeleteMeasuresOnDeletedProfilesMigration;
import org.sonar.server.db.migrations.v50.InsertProjectsAuthorizationUpdatedAtMigration;
@@ -69,6 +60,7 @@ public interface DatabaseMigrations {
// 4.5
AddMissingRuleParameterDefaultValuesMigration.class,
DeleteMeasuresOnDeletedProfilesMigration.class,
+ AddMissingCustomRuleParametersMigration.class,
// 5.0
InsertProjectsAuthorizationUpdatedAtMigration.class
diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigration.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigration.java
new file mode 100644
index 00000000000..4df912365da
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigration.java
@@ -0,0 +1,118 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.db.migrations.v45;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.migration.v45.Migration45Mapper;
+import org.sonar.core.persistence.migration.v45.Rule;
+import org.sonar.core.persistence.migration.v45.RuleParameter;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.db.migrations.DatabaseMigration;
+
+import javax.annotation.Nullable;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * See http://jira.codehaus.org/browse/SONAR-5575
+ *
+ * Add missing parameters (with no value) on each custom rules
+ *
+ * @since 4.5
+ */
+public class AddMissingCustomRuleParametersMigration implements DatabaseMigration {
+
+ private final DbClient db;
+ private final System2 system;
+
+ public AddMissingCustomRuleParametersMigration(DbClient db, System2 system) {
+ this.db = db;
+ this.system = system;
+ }
+
+ @Override
+ public void execute() {
+ DbSession session = db.openSession(false);
+ try {
+ Migration45Mapper mapper = session.getMapper(Migration45Mapper.class);
+
+ List<RuleParameter> templateRuleParams = mapper.selectAllTemplateRuleParameters();
+ Multimap<Integer, RuleParameter> templateRuleParamsByRuleId = ArrayListMultimap.create();
+ for (RuleParameter templateRuleParam : templateRuleParams) {
+ templateRuleParamsByRuleId.put(templateRuleParam.getRuleId(), templateRuleParam);
+ }
+
+ List<Rule> customRules = mapper.selectAllCustomRules();
+ Multimap<Integer, Integer> customRuleIdsByTemplateRuleId = HashMultimap.create();
+ for (Rule customRule : customRules) {
+ customRuleIdsByTemplateRuleId.put(customRule.getTemplateId(), customRule.getId());
+ }
+
+ List<RuleParameter> customRuleParams = mapper.selectAllCustomRuleParameters();
+ Multimap<Integer, RuleParameter> customRuleParamsByRuleId = ArrayListMultimap.create();
+ for (RuleParameter customRuleParam : customRuleParams) {
+ customRuleParamsByRuleId.put(customRuleParam.getRuleId(), customRuleParam);
+ }
+
+ // For each parameters of template rules, verify that each custom rules has the parameter
+ for (Integer templateRuleId : templateRuleParamsByRuleId.keySet()) {
+ for (RuleParameter templateRuleParam : templateRuleParamsByRuleId.get(templateRuleId)) {
+ // Each custom rule should have this parameter
+ for (Integer customRuleId : customRuleIdsByTemplateRuleId.get(templateRuleId)) {
+ if (!hasParameter(templateRuleParam.getName(), customRuleParamsByRuleId.get(customRuleId))) {
+ // Insert new custom rule parameter
+ mapper.insertRuleParameter(new RuleParameter()
+ .setRuleId(customRuleId)
+ .setRuleTemplateId(templateRuleId)
+ .setName(templateRuleParam.getName())
+ .setDescription(templateRuleParam.getDescription())
+ .setType(templateRuleParam.getType())
+ );
+
+ // Update updated at date of custom rule in order to allow E/S indexation
+ mapper.updateRuleUpdateAt(customRuleId, new Date(system.now()));
+ }
+ }
+ }
+ }
+
+ session.commit();
+ } finally {
+ session.close();
+ }
+ }
+
+ private boolean hasParameter(final String parameter, Collection<RuleParameter> customRuleParams) {
+ return Iterables.any(customRuleParams, new Predicate<RuleParameter>() {
+ @Override
+ public boolean apply(@Nullable RuleParameter input) {
+ return input != null && input.getName().equals(parameter);
+ }
+ });
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java
index 0a60c46eca9..aa17fafdffc 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java
@@ -33,6 +33,7 @@ import org.sonar.server.db.DbClient;
import org.sonar.server.rule.index.RuleDoc;
import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
public class RuleCreator implements ServerComponent {
@@ -168,20 +169,18 @@ public class RuleCreator implements ServerComponent {
dbClient.ruleDao().insert(dbSession, ruleDto);
for (RuleParamDto templateRuleParamDto : dbClient.ruleDao().findRuleParamsByRuleKey(dbSession, templateRuleDto.getKey())) {
- String newRuleParam = newRule.parameter(templateRuleParamDto.getName());
- if (newRuleParam != null) {
- createCustomRuleParams(newRuleParam, ruleDto, templateRuleParamDto, dbSession);
- }
+ String customRuleParamValue = Strings.emptyToNull(newRule.parameter(templateRuleParamDto.getName()));
+ createCustomRuleParams(customRuleParamValue, ruleDto, templateRuleParamDto, dbSession);
}
return ruleKey;
}
- private void createCustomRuleParams(String param, RuleDto ruleDto, RuleParamDto templateRuleParam, DbSession dbSession){
+ private void createCustomRuleParams(@Nullable String paramValue, RuleDto ruleDto, RuleParamDto templateRuleParam, DbSession dbSession){
RuleParamDto ruleParamDto = RuleParamDto.createFor(ruleDto)
.setName(templateRuleParam.getName())
.setType(templateRuleParam.getType())
.setDescription(templateRuleParam.getDescription())
- .setDefaultValue(param);
+ .setDefaultValue(paramValue);
dbClient.ruleDao().addRuleParam(dbSession, ruleDto, ruleParamDto);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java
index adeeabfa2bd..69f7f2a5db5 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java
@@ -39,7 +39,12 @@ import org.sonar.core.technicaldebt.db.CharacteristicDto;
import org.sonar.server.db.DbClient;
import org.sonar.server.user.UserSession;
-import java.util.*;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import static com.google.common.collect.Lists.newArrayList;
public class RuleUpdater implements ServerComponent {
@@ -265,8 +270,7 @@ public class RuleUpdater implements ServerComponent {
throw new IllegalStateException(String.format("Template %s of rule %s does not exist",
customRule.getTemplateId(), customRule.getKey()));
}
- List<RuleParamDto> templateRuleParams = dbClient.ruleDao().findRuleParamsByRuleKey(dbSession, templateRule.getKey());
- List<String> paramKeys = new ArrayList<String>();
+ List<String> paramKeys = newArrayList();
// Load active rules and its parameters in cache
Multimap<RuleDto, ActiveRuleDto> activeRules = ArrayListMultimap.create();
@@ -278,36 +282,33 @@ public class RuleUpdater implements ServerComponent {
}
}
- // Browse custom rule parameters to update or delete them
+ // Browse custom rule parameters to create, update or delete them
deleteOrUpdateParameters(dbSession, update, customRule, paramKeys, activeRules, activeRuleParams);
-
- // Browse template rule parameters to create new parameters
- createNewParameters(dbSession, update, customRule, templateRuleParams, paramKeys, activeRules);
}
}
private void deleteOrUpdateParameters(DbSession dbSession, RuleUpdate update, RuleDto customRule, List<String> paramKeys,
- Multimap<RuleDto, ActiveRuleDto> activeRules, Multimap<ActiveRuleDto, ActiveRuleParamDto> activeRuleParams) {
+ Multimap<RuleDto, ActiveRuleDto> activeRules, Multimap<ActiveRuleDto, ActiveRuleParamDto> activeRuleParams) {
for (RuleParamDto ruleParamDto : dbClient.ruleDao().findRuleParamsByRuleKey(dbSession, update.getRuleKey())) {
String key = ruleParamDto.getName();
- String value = update.parameter(key);
- if (!Strings.isNullOrEmpty(value)) {
- // Update rule param
- ruleParamDto.setDefaultValue(value);
- dbClient.ruleDao().updateRuleParam(dbSession, customRule, ruleParamDto);
+ String value = Strings.emptyToNull(update.parameter(key));
+
+ // Update rule param
+ ruleParamDto.setDefaultValue(value);
+ dbClient.ruleDao().updateRuleParam(dbSession, customRule, ruleParamDto);
- // Update linked active rule params
+ if (value != null) {
+ // Update linked active rule params or create new one
for (ActiveRuleDto activeRuleDto : activeRules.get(customRule)) {
for (ActiveRuleParamDto activeRuleParamDto : activeRuleParams.get(activeRuleDto)) {
if (activeRuleParamDto.getKey().equals(key)) {
dbClient.activeRuleDao().updateParam(dbSession, activeRuleDto, activeRuleParamDto.setValue(value));
+ } else {
+ dbClient.activeRuleDao().addParam(dbSession, activeRuleDto, ActiveRuleParamDto.createFor(ruleParamDto).setValue(value));
}
}
}
} else {
- // Delete rule param
- dbClient.ruleDao().removeRuleParam(dbSession, customRule, ruleParamDto);
-
// Delete linked active rule params
for (ActiveRuleDto activeRuleDto : activeRules.get(customRule)) {
for (ActiveRuleParamDto activeRuleParamDto : activeRuleParams.get(activeRuleDto)) {
@@ -321,31 +322,6 @@ public class RuleUpdater implements ServerComponent {
}
}
- private void createNewParameters(DbSession dbSession, RuleUpdate update, RuleDto customRule, List<RuleParamDto> templateRuleParams, List<String> paramKeys,
- Multimap<RuleDto, ActiveRuleDto> activeRules) {
- for (RuleParamDto templateRuleParam : templateRuleParams) {
- String key = templateRuleParam.getName();
- if (!paramKeys.contains(key)) {
- String value = update.parameter(key);
- if (!Strings.isNullOrEmpty(value)) {
-
- // Create new param
- RuleParamDto paramDto = RuleParamDto.createFor(customRule)
- .setName(key)
- .setDescription(templateRuleParam.getDescription())
- .setDefaultValue(value)
- .setType(templateRuleParam.getType());
- dbClient.ruleDao().addRuleParam(dbSession, customRule, paramDto);
-
- // Create new active rule param
- for (ActiveRuleDto activeRuleDto : activeRules.get(customRule)) {
- dbClient.activeRuleDao().addParam(dbSession, activeRuleDto, ActiveRuleParamDto.createFor(paramDto).setValue(value));
- }
- }
- }
- }
- }
-
/**
* Data loaded before update
*/
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/design/file_design.html.erb b/server/sonar-server/src/main/resources/org/sonar/server/design/file_design.html.erb
index 2fcac1fc7a9..63e9020b77b 100644
--- a/server/sonar-server/src/main/resources/org/sonar/server/design/file_design.html.erb
+++ b/server/sonar-server/src/main/resources/org/sonar/server/design/file_design.html.erb
@@ -1,38 +1,110 @@
<%
+ dsm_url = ApplicationController.root_context + '/design/index/' + @resource.key
+
file_tangle_index=measure('file_tangle_index')
if file_tangle_index
file_cycles=measure('file_cycles')
file_feedback_edges=measure('file_feedback_edges')
%>
-<table width="100%">
- <tbody>
- <tr>
- <td valign="top" width="50%">
- <div class="dashbox">
- <p class="title"><%= message('widget.file_design.file_tangle_index') -%></p>
- <p>
- <span class="big"><%= format_measure(file_tangle_index, :suffix => '', :default => '-', :url => url_for_drilldown('file_tangle_index')) -%></span> <%= dashboard_configuration.selected_period? ? format_variation(file_tangle_index) : trend_icon(file_tangle_index, :big => true) -%>
- </p>
- <% if file_cycles %>
- <p>
- > <%= format_measure(file_cycles, :suffix => message('widget.file_design.cycles.suffix'), :url => url_for_drilldown('file_cycles')) %> <%= dashboard_configuration.selected_period? ? format_variation(file_cycles) : trend_icon(file_cycles) -%>
- </p>
- <% end %>
+<div class="widget-row">
+ <div class="widget-span widget-span-5">
+ <div class="widget-measure-container">
+ <div class="widget-measure widget-measure-main">
+ <span class="widget-label"><%= message('widget.file_design.file_tangle_index') -%></span>
+ <span class="nowrap">
+ <%= format_measure(file_tangle_index, :suffix => '', :default => '-', :url => dsm_url) -%>
+ <%= dashboard_configuration.selected_period? ? format_variation(file_tangle_index) : trend_icon(file_tangle_index, :big => true) -%>
+ </span>
+ </div>
+
+ <% if file_cycles %>
+ <div class="widget-measure">
+ <span class="widget-label"><%= message('widget.file_design.cycles.suffix') -%></span>
+ <span class="nowrap">
+ <span class="widget-medium">&gt;</span>
+ <%= format_measure(file_cycles, :default => '-', :url => dsm_url) %>
+ <%= dashboard_configuration.selected_period? ? format_variation(file_cycles) : trend_icon(file_cycles) -%>
+ </span>
</div>
- </td>
- <td valign="top" width="50%">
- <% if file_feedback_edges %>
- <div class="dashbox">
- <p class="title"><%= message('widget.file_design.suspect_file_dependencies') -%></p>
- <p>
- <span class="big"><%= format_measure(file_feedback_edges, :url => url_for_drilldown('file_feedback_edges')) -%></span> <%= dashboard_configuration.selected_period? ? format_variation(file_feedback_edges) : trend_icon(file_feedback_edges, :big => true) -%>
- </p>
+ <% end %>
+ </div>
+ </div>
+
+ <div class="widget-span widget-span-5">
+ <% if file_feedback_edges %>
+ <div class="widget-measure-container">
+ <div class="widget-measure widget-measure-main">
+ <span class="widget-label"><%= message('widget.file_design.suspect_file_dependencies') -%></span>
+ <span class="nowrap">
+ <%= format_measure(file_feedback_edges, :url => dsm_url) -%>
+ <%= dashboard_configuration.selected_period? ? format_variation(file_feedback_edges) : trend_icon(file_feedback_edges, :big => true) -%>
+ </span>
+ </div>
+ </div>
+ <% end %>
+ </div>
+</div>
+<%
+ else
+ package_tangle_index=measure('package_tangle_index')
+ if package_tangle_index
+ package_cycles=measure('package_cycles')
+ package_feedback_edges=measure('package_feedback_edges')
+ package_tangles=measure('package_tangles')
+%>
+<div class="widget-row">
+ <div class="widget-span widget-span-5">
+ <div class="widget-measure-container">
+ <div class="widget-measure widget-measure-main">
+ <span class="widget-label"><%= message('widget.package_design.package_tangle_index') -%></span>
+ <span class="nowrap">
+ <%= format_measure(package_tangle_index, :suffix => '', :default => '-', :url => dsm_url) %>
+ <%= dashboard_configuration.selected_period? ? format_variation(package_tangle_index) : trend_icon(package_tangle_index) -%>
+ </span>
+ </div>
+
+ <% if package_cycles %>
+ <div class="widget-measure">
+ <span class="widget-label"><%= message('widget.package_design.cycles.suffix') -%></span>
+ <span class="nowrap">
+ <span class="widget-medium">&gt;</span>
+ <%= format_measure(package_cycles, :default => '-', :url => dsm_url) %>
+ <%= dashboard_configuration.selected_period? ? format_variation(package_cycles) : trend_icon(package_cycles) -%>
+ </span>
+ </div>
+ <% end %>
+ </div>
+ </div>
+
+ <div class="widget-span widget-span-5">
+ <div class="widget-measure-container">
+ <div class="widget-measure widget-measure-main">
+ <span class="widget-label"><%= message('widget.package_design.dependencies_to_cut') -%></span>
+ </div>
+
+ <% if package_feedback_edges %>
+ <div class="widget-measure">
+ <span class="widget-label"><%= message('widget.package_design.between_packages.suffix') -%></span>
+ <span class="nowrap">
+ <%= format_measure(package_feedback_edges, :default => '-', :url => dsm_url) %>
+ <%= dashboard_configuration.selected_period? ? format_variation(package_feedback_edges) : trend_icon(package_feedback_edges) -%>
+ </span>
</div>
- <% end %>
- </td>
- </tr>
- </tbody>
-</table>
+ <% end %>
+
+ <% if package_tangles %>
+ <div class="widget-measure">
+ <span class="widget-label"><%= message('widget.package_design.between_files.suffix') -%></span>
+ <span class="nowrap">
+ <%= format_measure(package_tangles, :default => '-', :url => dsm_url) %>
+ <%= dashboard_configuration.selected_period? ? format_variation(package_tangles) : trend_icon(package_tangles) -%>
+ </span>
+ </div>
+ <% end %>
+ </div>
+ </div>
+</div>
<%
+ end
end
-%> \ No newline at end of file
+%>
diff --git a/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest.java b/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest.java
new file mode 100644
index 00000000000..f1db25496b6
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest.java
@@ -0,0 +1,78 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.db.migrations.v45;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.TestDatabase;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.db.migrations.DatabaseMigration;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class AddMissingCustomRuleParametersMigrationTest {
+
+ @ClassRule
+ public static TestDatabase db = new TestDatabase().schema(AddMissingCustomRuleParametersMigrationTest.class, "schema.sql");
+
+ DatabaseMigration migration;
+ System2 system = mock(System2.class);
+
+ @Before
+ public void setUp() throws Exception {
+ db.executeUpdateSql("truncate table rules");
+ db.executeUpdateSql("truncate table rules_parameters");
+ DbClient dbClient = new DbClient(db.database(), db.myBatis());
+ migration = new AddMissingCustomRuleParametersMigration(dbClient, system);
+ when(system.now()).thenReturn(DateUtils.parseDate("2014-10-09").getTime());
+ }
+
+ @Test
+ public void execute() throws Exception {
+ db.prepareDbUnit(getClass(), "execute.xml");
+
+ migration.execute();
+
+ db.assertDbUnit(getClass(), "execute-result.xml", "rules", "rules_parameters");
+ }
+
+ @Test
+ public void execute_when_custom_rule_have_no_parameter() throws Exception {
+ db.prepareDbUnit(getClass(), "execute_when_custom_rule_have_no_parameter.xml");
+
+ migration.execute();
+
+ db.assertDbUnit(getClass(), "execute_when_custom_rule_have_no_parameter-result.xml", "rules", "rules_parameters");
+ }
+
+ @Test
+ public void no_changes() throws Exception {
+ db.prepareDbUnit(getClass(), "no_changes.xml");
+
+ migration.execute();
+
+ db.assertDbUnit(getClass(), "no_changes.xml", "rules", "rules_parameters");
+ }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java
index 8751f33e0c2..4eee09b2ffe 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java
@@ -113,6 +113,55 @@ public class RuleCreatorMediumTest {
}
@Test
+ public void create_custom_rule_with_empty_parameter_value() throws Exception {
+ // insert template rule
+ RuleDto templateRule = createTemplateRule();
+
+ NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
+ .setName("My custom")
+ .setHtmlDescription("Some description")
+ .setSeverity(Severity.MAJOR)
+ .setStatus(RuleStatus.READY)
+ .setParameters(ImmutableMap.of("regex", ""));
+
+ RuleKey customRuleKey = creator.create(newRule);
+ dbSession.clearCache();
+
+ List<RuleParamDto> params = db.ruleDao().findRuleParamsByRuleKey(dbSession, customRuleKey);
+ assertThat(params).hasSize(1);
+
+ RuleParamDto param = params.get(0);
+ assertThat(param.getName()).isEqualTo("regex");
+ assertThat(param.getDescription()).isEqualTo("Reg ex");
+ assertThat(param.getType()).isEqualTo("STRING");
+ assertThat(param.getDefaultValue()).isNull();
+ }
+
+ @Test
+ public void create_custom_rule_with_no_parameter_value() throws Exception {
+ // insert template rule
+ RuleDto templateRule = createTemplateRule();
+
+ NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
+ .setName("My custom")
+ .setHtmlDescription("Some description")
+ .setSeverity(Severity.MAJOR)
+ .setStatus(RuleStatus.READY);
+
+ RuleKey customRuleKey = creator.create(newRule);
+ dbSession.clearCache();
+
+ List<RuleParamDto> params = db.ruleDao().findRuleParamsByRuleKey(dbSession, customRuleKey);
+ assertThat(params).hasSize(1);
+
+ RuleParamDto param = params.get(0);
+ assertThat(param.getName()).isEqualTo("regex");
+ assertThat(param.getDescription()).isEqualTo("Reg ex");
+ assertThat(param.getType()).isEqualTo("STRING");
+ assertThat(param.getDefaultValue()).isNull();
+ }
+
+ @Test
public void reactivate_custom_rule_if_already_exists_in_removed_status() throws Exception {
String key = "CUSTOM_RULE";
@@ -194,42 +243,6 @@ public class RuleCreatorMediumTest {
}
@Test
- public void not_fail_to_create_custom_rule_when_a_param_is_missing() throws Exception {
- // insert template rule
- RuleDto templateRule = createTemplateRule();
-
- NewRule newRule = NewRule.createForCustomRule("CUSTOM_RULE", templateRule.getKey())
- .setName("My custom")
- .setHtmlDescription("Some description")
- .setSeverity(Severity.MAJOR)
- .setStatus(RuleStatus.READY);
-
- RuleKey customRuleKey = creator.create(newRule);
- dbSession.clearCache();
-
- List<RuleParamDto> params = db.ruleDao().findRuleParamsByRuleKey(dbSession, customRuleKey);
- assertThat(params).hasSize(0);
- }
-
- @Test
- public void fail_to_create_custom_rule_when_missing_key() throws Exception {
- // insert template rule
- RuleDto templateRule = createTemplateRule();
-
- try {
- NewRule newRule = NewRule.createForCustomRule("", templateRule.getKey())
- .setName("My custom")
- .setHtmlDescription("Some description")
- .setSeverity(Severity.MAJOR)
- .setStatus(RuleStatus.READY)
- .setParameters(ImmutableMap.of("regex", "a.*"));
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Custom key should be set");
- }
- }
-
- @Test
public void fail_to_create_custom_rule_when_invalid_key() throws Exception {
// insert template rule
RuleDto templateRule = createTemplateRule();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java
index 18815797922..44f110aa685 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterMediumTest.java
@@ -400,8 +400,10 @@ public class RuleUpdaterMediumTest {
// Create template rule
RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001"));
ruleDao.insert(dbSession, templateRule);
- RuleParamDto templateRuleParam = RuleParamDto.createFor(templateRule).setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(".*");
- ruleDao.addRuleParam(dbSession, templateRule, templateRuleParam);
+ RuleParamDto templateRuleParam1 = RuleParamDto.createFor(templateRule).setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(".*");
+ RuleParamDto templateRuleParam2 = RuleParamDto.createFor(templateRule).setName("format").setType("STRING").setDescription("Format");
+ ruleDao.addRuleParam(dbSession, templateRule, templateRuleParam1);
+ ruleDao.addRuleParam(dbSession, templateRule, templateRuleParam2);
// Create custom rule
RuleDto customRule = RuleTesting.newCustomRule(templateRule)
@@ -410,7 +412,8 @@ public class RuleUpdaterMediumTest {
.setSeverity(Severity.MINOR)
.setStatus(RuleStatus.BETA);
ruleDao.insert(dbSession, customRule);
- ruleDao.addRuleParam(dbSession, customRule, templateRuleParam.setDefaultValue("a.*"));
+ ruleDao.addRuleParam(dbSession, customRule, templateRuleParam1.setDefaultValue("a.*"));
+ ruleDao.addRuleParam(dbSession, customRule, templateRuleParam2.setDefaultValue(null));
dbSession.commit();
@@ -432,10 +435,45 @@ public class RuleUpdaterMediumTest {
assertThat(customRuleReloaded.htmlDescription()).isEqualTo("New description");
assertThat(customRuleReloaded.severity()).isEqualTo("MAJOR");
assertThat(customRuleReloaded.status()).isEqualTo(RuleStatus.READY);
- assertThat(customRuleReloaded.params()).hasSize(1);
+ assertThat(customRuleReloaded.params()).hasSize(2);
+
+ assertThat(customRuleReloaded.params().get(0).defaultValue()).isEqualTo("b.*");
+ assertThat(customRuleReloaded.params().get(1).defaultValue()).isNull();
+ }
+
+ @Test
+ public void update_custom_rule_with_empty_parameter() throws Exception {
+ // Create template rule
+ RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001"));
+ ruleDao.insert(dbSession, templateRule);
+ RuleParamDto templateRuleParam = RuleParamDto.createFor(templateRule).setName("regex").setType("STRING").setDescription("Reg ex");
+ ruleDao.addRuleParam(dbSession, templateRule, templateRuleParam);
+ // Create custom rule
+ RuleDto customRule = RuleTesting.newCustomRule(templateRule)
+ .setName("Old name")
+ .setDescription("Old description")
+ .setSeverity(Severity.MINOR)
+ .setStatus(RuleStatus.BETA);
+ ruleDao.insert(dbSession, customRule);
+ ruleDao.addRuleParam(dbSession, customRule, templateRuleParam);
+
+ dbSession.commit();
+
+ // Update custom rule without setting a value for the parameter
+ RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey())
+ .setName("New name")
+ .setMarkdownDescription("New description")
+ .setSeverity("MAJOR")
+ .setStatus(RuleStatus.READY);
+ updater.update(update, UserSession.get());
+
+ dbSession.clearCache();
+
+ // Verify custom rule is updated
+ Rule customRuleReloaded = ruleIndex.getByKey(customRule.getKey());
RuleParam param = customRuleReloaded.params().get(0);
- assertThat(param.defaultValue()).isEqualTo("b.*");
+ assertThat(param.defaultValue()).isNull();
}
@Test
@@ -450,11 +488,12 @@ public class RuleUpdaterMediumTest {
RuleParamDto templateRuleParam3 = RuleParamDto.createFor(templateRule).setName("message").setType("STRING").setDescription("message");
ruleDao.addRuleParam(dbSession, templateRule, templateRuleParam3);
- // Create custom rule with 2 parameters
+ // Create custom rule
RuleDto customRule = RuleTesting.newCustomRule(templateRule).setSeverity(Severity.MAJOR).setLanguage("xoo");
ruleDao.insert(dbSession, customRule);
ruleDao.addRuleParam(dbSession, customRule, templateRuleParam1.setDefaultValue("a.*"));
ruleDao.addRuleParam(dbSession, customRule, templateRuleParam2.setDefaultValue("txt"));
+ ruleDao.addRuleParam(dbSession, customRule, templateRuleParam3);
// Create a quality profile
QualityProfileDto profileDto = QProfileTesting.newXooP1();
@@ -476,12 +515,13 @@ public class RuleUpdaterMediumTest {
// Verify custom rule parameters has been updated
Rule customRuleReloaded = ruleIndex.getByKey(customRule.getKey());
- assertThat(customRuleReloaded.params()).hasSize(2);
+ assertThat(customRuleReloaded.params()).hasSize(3);
assertThat(customRuleReloaded.param("regex")).isNotNull();
assertThat(customRuleReloaded.param("regex").defaultValue()).isEqualTo("b.*");
assertThat(customRuleReloaded.param("message")).isNotNull();
assertThat(customRuleReloaded.param("message").defaultValue()).isEqualTo("a message");
- assertThat(customRuleReloaded.param("format")).isNull();
+ assertThat(customRuleReloaded.param("format")).isNotNull();
+ assertThat(customRuleReloaded.param("format").defaultValue()).isNull();
RuleParam param = customRuleReloaded.params().get(0);
assertThat(param.defaultValue()).isEqualTo("b.*");
@@ -490,8 +530,8 @@ public class RuleUpdaterMediumTest {
ActiveRule activeRule = tester.get(ActiveRuleIndex.class).getByKey(ActiveRuleKey.of(profileDto.getKey(), customRule.getKey()));
assertThat(activeRule.params()).hasSize(2);
assertThat(activeRule.params().get("regex")).isEqualTo("b.*");
- assertThat(activeRule.params().get("format")).isNull();
assertThat(activeRule.params().get("message")).isEqualTo("a message");
+ assertThat(activeRule.params().get("format")).isNull();
// Verify that severity has not changed
assertThat(activeRule.severity()).isEqualTo(Severity.BLOCKER);
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute-result.xml
new file mode 100644
index 00000000000..a4b4ab4411b
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute-result.xml
@@ -0,0 +1,31 @@
+<dataset>
+
+ <!-- Template rule -->
+ <rules id="1" plugin_rule_key="ArchitecturalConstraint" plugin_name="xoo" name="Architectural constraint" description="Architectural constraint" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" tags="[null]" system_tags="[null]" plugin_config_key="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[true]" template_id="[null]" created_at="2014-01-01" updated_at="2014-01-01"/>
+ <rules_parameters id="1" rule_id="1" name="max" param_type="INT" default_value="10" description="[null]" />
+ <rules_parameters id="2" rule_id="1" name="format" param_type="STRING" default_value="txt" description="[null]" />
+ <rules_parameters id="3" rule_id="1" name="type" param_type="STRING" default_value="[null]" description="[null]" />
+ <rules_parameters id="4" rule_id="1" name="param" param_type="STRING" default_value="" description="[null]" />
+
+ <!-- Custom rule, 2 parameters should be added -->
+ <rules id="2" plugin_rule_key="ArchitecturalConstraint_2" plugin_name="xoo" name="Architectural constraint 2" description="Architectural constraint 2" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" tags="[null]" system_tags="[null]" plugin_config_key="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="1" created_at="2014-01-01" updated_at="2014-10-09"/>
+ <rules_parameters id="5" rule_id="2" name="max" param_type="INT" default_value="10" description="[null]" />
+ <rules_parameters id="6" rule_id="2" name="format" param_type="STRING" default_value="csv" description="[null]" />
+ <rules_parameters id="7" rule_id="2" name="type" param_type="STRING" default_value="[null]" description="[null]" />
+ <rules_parameters id="8" rule_id="2" name="param" param_type="STRING" default_value="[null]" description="[null]" />
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute.xml
new file mode 100644
index 00000000000..58b9732cf61
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute.xml
@@ -0,0 +1,29 @@
+<dataset>
+
+ <!-- Template rule -->
+ <rules id="1" plugin_rule_key="ArchitecturalConstraint" plugin_name="xoo" name="Architectural constraint" description="Architectural constraint" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" tags="[null]" system_tags="[null]" plugin_config_key="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[true]" template_id="[null]" created_at="2014-01-01" updated_at="2014-01-01"/>
+ <rules_parameters id="1" rule_id="1" name="max" param_type="INT" default_value="10" description="[null]" />
+ <rules_parameters id="2" rule_id="1" name="format" param_type="STRING" default_value="txt" description="[null]" />
+ <rules_parameters id="3" rule_id="1" name="type" param_type="STRING" default_value="[null]" description="[null]" />
+ <rules_parameters id="4" rule_id="1" name="param" param_type="STRING" default_value="" description="[null]" />
+
+ <!-- Custom rule, 2 parameters are existing, 2 parameters should be added -->
+ <rules id="2" plugin_rule_key="ArchitecturalConstraint_2" plugin_name="xoo" name="Architectural constraint 2" description="Architectural constraint 2" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" tags="[null]" system_tags="[null]" plugin_config_key="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="1" created_at="2014-01-01" updated_at="2014-01-01"/>
+ <rules_parameters id="5" rule_id="2" name="max" param_type="INT" default_value="10" description="[null]" />
+ <rules_parameters id="6" rule_id="2" name="format" param_type="STRING" default_value="csv" description="[null]" />
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute_when_custom_rule_have_no_parameter-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute_when_custom_rule_have_no_parameter-result.xml
new file mode 100644
index 00000000000..76c7c186008
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute_when_custom_rule_have_no_parameter-result.xml
@@ -0,0 +1,31 @@
+<dataset>
+
+ <!-- Template rule -->
+ <rules id="1" plugin_rule_key="ArchitecturalConstraint" plugin_name="xoo" name="Architectural constraint" description="Architectural constraint" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" tags="[null]" system_tags="[null]" plugin_config_key="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[true]" template_id="[null]" created_at="2014-01-01" updated_at="2014-01-01"/>
+ <rules_parameters id="1" rule_id="1" name="max" param_type="INT" default_value="10" description="[null]" />
+ <rules_parameters id="2" rule_id="1" name="format" param_type="STRING" default_value="txt" description="[null]" />
+ <rules_parameters id="3" rule_id="1" name="type" param_type="STRING" default_value="[null]" description="[null]" />
+ <rules_parameters id="4" rule_id="1" name="param" param_type="STRING" default_value="" description="[null]" />
+
+ <!-- Custom rule, 0 parameter are existing, 4 parameters should be added -->
+ <rules id="3" plugin_rule_key="ArchitecturalConstraint_3" plugin_name="xoo" name="Architectural constraint 3" description="Architectural constraint 3" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" tags="[null]" system_tags="[null]" plugin_config_key="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="1" created_at="2014-01-01" updated_at="2014-10-09"/>
+ <rules_parameters id="5" rule_id="3" name="max" param_type="INT" default_value="[null]" description="[null]" />
+ <rules_parameters id="6" rule_id="3" name="format" param_type="STRING" default_value="[null]" description="[null]" />
+ <rules_parameters id="7" rule_id="3" name="type" param_type="STRING" default_value="[null]" description="[null]" />
+ <rules_parameters id="8" rule_id="3" name="param" param_type="STRING" default_value="[null]" description="[null]" />
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute_when_custom_rule_have_no_parameter.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute_when_custom_rule_have_no_parameter.xml
new file mode 100644
index 00000000000..dd676e5d869
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/execute_when_custom_rule_have_no_parameter.xml
@@ -0,0 +1,27 @@
+<dataset>
+
+ <!-- Template rule -->
+ <rules id="1" plugin_rule_key="ArchitecturalConstraint" plugin_name="xoo" name="Architectural constraint" description="Architectural constraint" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" tags="[null]" system_tags="[null]" plugin_config_key="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[true]" template_id="[null]" created_at="2014-01-01" updated_at="2014-01-01"/>
+ <rules_parameters id="1" rule_id="1" name="max" param_type="INT" default_value="10" description="[null]" />
+ <rules_parameters id="2" rule_id="1" name="format" param_type="STRING" default_value="txt" description="[null]" />
+ <rules_parameters id="3" rule_id="1" name="type" param_type="STRING" default_value="[null]" description="[null]" />
+ <rules_parameters id="4" rule_id="1" name="param" param_type="STRING" default_value="" description="[null]" />
+
+ <!-- Custom rule, 0 parameter are existing, 4 parameters should be added -->
+ <rules id="3" plugin_rule_key="ArchitecturalConstraint_3" plugin_name="xoo" name="Architectural constraint 3" description="Architectural constraint 3" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" tags="[null]" system_tags="[null]" plugin_config_key="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="1" created_at="2014-01-01" updated_at="2014-01-01"/>
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/no_changes.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/no_changes.xml
new file mode 100644
index 00000000000..ed072ad9461
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/no_changes.xml
@@ -0,0 +1,25 @@
+<dataset>
+
+ <!-- Template rule -->
+ <rules id="10" plugin_rule_key="Rule2" plugin_name="xoo" name="Rule2" description="Rule2" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" tags="[null]" system_tags="[null]" plugin_config_key="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[true]" template_id="[null]" created_at="2014-01-01" updated_at="2014-01-01"/>
+ <rules_parameters id="10" rule_id="10" name="max" param_type="INT" default_value="10" description="[null]" />
+
+ <!-- Custom rule, no parameter should be added -->
+ <rules id="11" plugin_rule_key="Rule2_2" plugin_name="xoo" name="Rule2_2" description="Rule2_2" status="READY" priority="1" language="xoo"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" description_format="HTML" tags="[null]" system_tags="[null]" plugin_config_key="[null]"
+ characteristic_id="[null]" default_characteristic_id="[null]"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="10" created_at="2014-01-01" updated_at="2014-01-01"/>
+ <rules_parameters id="11" rule_id="11" name="max" param_type="INT" default_value="10" description="[null]" />
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/schema.sql b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/schema.sql
new file mode 100644
index 00000000000..0bf38617681
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v45/AddMissingCustomRuleParametersMigrationTest/schema.sql
@@ -0,0 +1,40 @@
+CREATE TABLE "RULES_PARAMETERS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "RULE_ID" INTEGER NOT NULL,
+ "NAME" VARCHAR(128) NOT NULL,
+ "PARAM_TYPE" VARCHAR(512) NOT NULL,
+ "DEFAULT_VALUE" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000)
+);
+
+CREATE TABLE "RULES" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL,
+ "PLUGIN_NAME" VARCHAR(255) NOT NULL,
+ "DESCRIPTION" VARCHAR(16777215),
+ "DESCRIPTION_FORMAT" VARCHAR(20),
+ "PRIORITY" INTEGER,
+ "IS_TEMPLATE" BOOLEAN DEFAULT FALSE,
+ "TEMPLATE_ID" INTEGER,
+ "PLUGIN_CONFIG_KEY" VARCHAR(500),
+ "NAME" VARCHAR(200),
+ "STATUS" VARCHAR(40),
+ "LANGUAGE" VARCHAR(20),
+ "NOTE_DATA" CLOB(2147483647),
+ "NOTE_USER_LOGIN" VARCHAR(255),
+ "NOTE_CREATED_AT" TIMESTAMP,
+ "NOTE_UPDATED_AT" TIMESTAMP,
+ "CHARACTERISTIC_ID" INTEGER,
+ "DEFAULT_CHARACTERISTIC_ID" INTEGER,
+ "REMEDIATION_FUNCTION" VARCHAR(20),
+ "DEFAULT_REMEDIATION_FUNCTION" VARCHAR(20),
+ "REMEDIATION_COEFF" VARCHAR(20),
+ "DEFAULT_REMEDIATION_COEFF" VARCHAR(20),
+ "REMEDIATION_OFFSET" VARCHAR(20),
+ "DEFAULT_REMEDIATION_OFFSET" VARCHAR(20),
+ "EFFORT_TO_FIX_DESCRIPTION" VARCHAR(4000),
+ "TAGS" VARCHAR(4000),
+ "SYSTEM_TAGS" VARCHAR(4000),
+ "CREATED_AT" TIMESTAMP,
+ "UPDATED_AT" TIMESTAMP
+);
diff --git a/server/sonar-web/src/main/coffee/coding-rules/views/coding-rules-custom-rule-creation-view.coffee b/server/sonar-web/src/main/coffee/coding-rules/views/coding-rules-custom-rule-creation-view.coffee
index 810f4ccfd89..4728cb45e5b 100644
--- a/server/sonar-web/src/main/coffee/coding-rules/views/coding-rules-custom-rule-creation-view.coffee
+++ b/server/sonar-web/src/main/coffee/coding-rules/views/coding-rules-custom-rule-creation-view.coffee
@@ -68,7 +68,11 @@ define [
postData.prevent_reactivation = true
params = @ui.customRuleCreationParameters.map(->
- key: jQuery(@).prop('name'), value: jQuery(@).val() || jQuery(@).prop('placeholder') || '').get()
+ node = jQuery(@)
+ value = node.val()
+ if !value and action == 'create'
+ value = node.prop('placeholder') || ''
+ key: node.prop('name'), value: value).get()
postData.params = (params.map (param) -> param.key + '=' + param.value).join(';')
@sendRequest(action, postData)
diff --git a/server/sonar-web/src/main/js/widgets/timeline.js b/server/sonar-web/src/main/js/widgets/timeline.js
index 23ab743cd23..3718852e1bd 100644
--- a/server/sonar-web/src/main/js/widgets/timeline.js
+++ b/server/sonar-web/src/main/js/widgets/timeline.js
@@ -153,6 +153,9 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
.ticks(5);
+ this.showLimitHistoryMessage();
+
+
// Configure lines and points
this.lines = [];
this.glines = [];
@@ -281,6 +284,17 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
};
+ window.SonarWidgets.Timeline.prototype.showLimitHistoryMessage = function () {
+ var minEvent = d3.min(this.events(), function (d) {
+ return d.d;
+ }),
+ minData = this.time.domain()[0];
+ if (minEvent < minData) {
+ var maxResultsReachedLabel = this.container.append('div').text(this.limitedHistoricalData);
+ maxResultsReachedLabel.classed('max-results-reached-message', true);
+ }
+ };
+
window.SonarWidgets.Timeline.prototype.update = function() {
var widget = this,
diff --git a/server/sonar-web/src/main/less/style.less b/server/sonar-web/src/main/less/style.less
index 72388c0ba34..a0c6ec7f7ba 100644
--- a/server/sonar-web/src/main/less/style.less
+++ b/server/sonar-web/src/main/less/style.less
@@ -2579,17 +2579,17 @@ div.rule-title {
}
}
-.sonar-d3 .max-results-reached-message {
+.max-results-reached-message {
font-size: 12px;
}
-.sonar-d3 div.max-results-reached-message {
+div.max-results-reached-message {
margin-top: 10px;
color: #777;
text-align: center;
}
-.sonar-d3 text.max-results-reached-message {
+text.max-results-reached-message {
fill: #777;
}
@@ -2607,11 +2607,6 @@ div.rule-title {
.sonar-d3 .treemap-cell-drilldown {
cursor: pointer;
- .trans;
-
- &:hover .treemap-inner {
- text-decoration: underline;
- }
}
.sonar-d3 .treemap-inner {
diff --git a/server/sonar-web/src/main/less/ui.less b/server/sonar-web/src/main/less/ui.less
index 710a9157cef..89ecef1598b 100644
--- a/server/sonar-web/src/main/less/ui.less
+++ b/server/sonar-web/src/main/less/ui.less
@@ -339,6 +339,8 @@ input[type=button] {
font-weight: 500;
text-transform: uppercase;
}
+
+ td { padding: 0 5px; }
}
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/601_add_missing_custom_rule_parameters.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/601_add_missing_custom_rule_parameters.rb
new file mode 100644
index 00000000000..55d04675c93
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/601_add_missing_custom_rule_parameters.rb
@@ -0,0 +1,30 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube 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.
+#
+# SonarQube 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.
+#
+
+#
+# SonarQube 4.5.1
+# SONAR-5575
+#
+class AddMissingCustomRuleParameters < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration 'org.sonar.server.db.migrations.v45.AddMissingCustomRuleParametersMigration'
+ end
+end