aboutsummaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-05-19 10:50:08 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2014-05-19 11:31:11 +0200
commit3bd0d648f1ea9b8d8724ec0cd2b3a8d13ff90951 (patch)
treeb64ea01ca143829d8089301c20de866cb51ef187 /plugins
parent0bab6ec48f16ad6b83c80997cfa6fb69edd3930d (diff)
downloadsonarqube-3bd0d648f1ea9b8d8724ec0cd2b3a8d13ff90951.tar.gz
sonarqube-3bd0d648f1ea9b8d8724ec0cd2b3a8d13ff90951.zip
SONAR-5216 Generate profile events for multi language projects
Diffstat (limited to 'plugins')
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java93
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileEventsSensor.java100
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/description.html.erb4
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileEventsSensorTest.java167
4 files changed, 85 insertions, 279 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
index 6a7499e2332..eb8468ba5b6 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
@@ -20,7 +20,11 @@
package org.sonar.plugins.core;
import com.google.common.collect.ImmutableList;
-import org.sonar.api.*;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.Properties;
+import org.sonar.api.Property;
+import org.sonar.api.PropertyType;
+import org.sonar.api.SonarPlugin;
import org.sonar.api.checks.NoSonarFilter;
import org.sonar.core.timemachine.Periods;
import org.sonar.plugins.core.batch.IndexProjectPostJob;
@@ -28,19 +32,89 @@ import org.sonar.plugins.core.charts.DistributionAreaChart;
import org.sonar.plugins.core.charts.DistributionBarChart;
import org.sonar.plugins.core.charts.XradarChart;
import org.sonar.plugins.core.colorizers.JavaColorizerFormat;
-import org.sonar.plugins.core.dashboards.*;
-import org.sonar.plugins.core.issue.*;
-import org.sonar.plugins.core.issue.notification.*;
+import org.sonar.plugins.core.dashboards.GlobalDefaultDashboard;
+import org.sonar.plugins.core.dashboards.ProjectDefaultDashboard;
+import org.sonar.plugins.core.dashboards.ProjectHotspotDashboard;
+import org.sonar.plugins.core.dashboards.ProjectIssuesDashboard;
+import org.sonar.plugins.core.dashboards.ProjectTimeMachineDashboard;
+import org.sonar.plugins.core.issue.CountFalsePositivesDecorator;
+import org.sonar.plugins.core.issue.CountUnresolvedIssuesDecorator;
+import org.sonar.plugins.core.issue.InitialOpenIssuesSensor;
+import org.sonar.plugins.core.issue.InitialOpenIssuesStack;
+import org.sonar.plugins.core.issue.IssueHandlers;
+import org.sonar.plugins.core.issue.IssueTracking;
+import org.sonar.plugins.core.issue.IssueTrackingDecorator;
+import org.sonar.plugins.core.issue.IssuesDensityDecorator;
+import org.sonar.plugins.core.issue.WeightedIssuesDecorator;
+import org.sonar.plugins.core.issue.notification.ChangesOnMyIssueNotificationDispatcher;
+import org.sonar.plugins.core.issue.notification.IssueChangesEmailTemplate;
+import org.sonar.plugins.core.issue.notification.NewFalsePositiveNotificationDispatcher;
+import org.sonar.plugins.core.issue.notification.NewIssuesEmailTemplate;
+import org.sonar.plugins.core.issue.notification.NewIssuesNotificationDispatcher;
+import org.sonar.plugins.core.issue.notification.SendIssueNotificationsPostJob;
import org.sonar.plugins.core.measurefilters.MyFavouritesFilter;
import org.sonar.plugins.core.measurefilters.ProjectFilter;
import org.sonar.plugins.core.notifications.alerts.NewAlerts;
import org.sonar.plugins.core.security.ApplyProjectRolesDecorator;
-import org.sonar.plugins.core.sensors.*;
-import org.sonar.plugins.core.timemachine.*;
+import org.sonar.plugins.core.sensors.BranchCoverageDecorator;
+import org.sonar.plugins.core.sensors.CommentDensityDecorator;
+import org.sonar.plugins.core.sensors.CoverageDecorator;
+import org.sonar.plugins.core.sensors.CoverageMeasurementFilter;
+import org.sonar.plugins.core.sensors.DirectoriesDecorator;
+import org.sonar.plugins.core.sensors.FileHashSensor;
+import org.sonar.plugins.core.sensors.FilesDecorator;
+import org.sonar.plugins.core.sensors.ItBranchCoverageDecorator;
+import org.sonar.plugins.core.sensors.ItCoverageDecorator;
+import org.sonar.plugins.core.sensors.ItLineCoverageDecorator;
+import org.sonar.plugins.core.sensors.LineCoverageDecorator;
+import org.sonar.plugins.core.sensors.ManualMeasureDecorator;
+import org.sonar.plugins.core.sensors.OverallBranchCoverageDecorator;
+import org.sonar.plugins.core.sensors.OverallCoverageDecorator;
+import org.sonar.plugins.core.sensors.OverallLineCoverageDecorator;
+import org.sonar.plugins.core.sensors.ProjectLinksSensor;
+import org.sonar.plugins.core.sensors.UnitTestDecorator;
+import org.sonar.plugins.core.sensors.VersionEventsSensor;
+import org.sonar.plugins.core.timemachine.NewCoverageAggregator;
+import org.sonar.plugins.core.timemachine.NewCoverageFileAnalyzer;
+import org.sonar.plugins.core.timemachine.NewItCoverageFileAnalyzer;
+import org.sonar.plugins.core.timemachine.NewOverallCoverageFileAnalyzer;
+import org.sonar.plugins.core.timemachine.TendencyDecorator;
+import org.sonar.plugins.core.timemachine.TimeMachineConfigurationPersister;
+import org.sonar.plugins.core.timemachine.VariationDecorator;
import org.sonar.plugins.core.web.TestsViewer;
-import org.sonar.plugins.core.widgets.*;
-import org.sonar.plugins.core.widgets.issues.*;
-import org.sonar.plugins.core.widgets.measures.*;
+import org.sonar.plugins.core.widgets.AlertsWidget;
+import org.sonar.plugins.core.widgets.BubbleChartWidget;
+import org.sonar.plugins.core.widgets.ComplexityWidget;
+import org.sonar.plugins.core.widgets.CoverageWidget;
+import org.sonar.plugins.core.widgets.CustomMeasuresWidget;
+import org.sonar.plugins.core.widgets.DescriptionWidget;
+import org.sonar.plugins.core.widgets.DocumentationCommentsWidget;
+import org.sonar.plugins.core.widgets.DuplicationsWidget;
+import org.sonar.plugins.core.widgets.EventsWidget;
+import org.sonar.plugins.core.widgets.HotspotMetricWidget;
+import org.sonar.plugins.core.widgets.HotspotMostViolatedResourcesWidget;
+import org.sonar.plugins.core.widgets.HotspotMostViolatedRulesWidget;
+import org.sonar.plugins.core.widgets.ItCoverageWidget;
+import org.sonar.plugins.core.widgets.ProjectFileCloudWidget;
+import org.sonar.plugins.core.widgets.SizeWidget;
+import org.sonar.plugins.core.widgets.TechnicalDebtPyramidWidget;
+import org.sonar.plugins.core.widgets.TimeMachineWidget;
+import org.sonar.plugins.core.widgets.TimelineWidget;
+import org.sonar.plugins.core.widgets.TreemapWidget;
+import org.sonar.plugins.core.widgets.WelcomeWidget;
+import org.sonar.plugins.core.widgets.issues.ActionPlansWidget;
+import org.sonar.plugins.core.widgets.issues.FalsePositiveIssuesWidget;
+import org.sonar.plugins.core.widgets.issues.IssueFilterWidget;
+import org.sonar.plugins.core.widgets.issues.IssuesWidget;
+import org.sonar.plugins.core.widgets.issues.MyUnresolvedIssuesWidget;
+import org.sonar.plugins.core.widgets.issues.UnresolvedIssuesPerAssigneeWidget;
+import org.sonar.plugins.core.widgets.issues.UnresolvedIssuesStatusesWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterAsBubbleChartWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterAsCloudWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterAsHistogramWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterAsPieChartWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterListWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterTreemapWidget;
import java.util.List;
@@ -285,7 +359,6 @@ public final class CorePlugin extends SonarPlugin {
NewFalsePositiveNotificationDispatcher.newMetadata(),
// batch
- ProfileEventsSensor.class,
ProjectLinksSensor.class,
UnitTestDecorator.class,
VersionEventsSensor.class,
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileEventsSensor.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileEventsSensor.java
deleted file mode 100644
index c21c6304458..00000000000
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileEventsSensor.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.plugins.core.sensors;
-
-import org.sonar.api.batch.*;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.Project;
-import org.sonar.batch.rule.RulesProfileWrapper;
-
-import java.util.List;
-
-public class ProfileEventsSensor implements Sensor {
-
- private final RulesProfile profile;
- private final TimeMachine timeMachine;
- private final FileSystem fs;
-
- public ProfileEventsSensor(RulesProfile profile, TimeMachine timeMachine, FileSystem fs) {
- this.profile = profile;
- this.timeMachine = timeMachine;
- this.fs = fs;
- }
-
- public boolean shouldExecuteOnProject(Project project) {
- // Views will define a fake profile
- return profile instanceof RulesProfileWrapper;
- }
-
- public void analyse(Project project, SensorContext context) {
- RulesProfileWrapper profileWrapper = (RulesProfileWrapper) profile;
- for (String languageKey : fs.languages()) {
- RulesProfile realProfile = profileWrapper.getProfileByLanguage(languageKey);
- Measure pastProfileMeasure = getPreviousMeasure(project, CoreMetrics.PROFILE);
- if (pastProfileMeasure == null) {
- // first analysis
- return;
- }
- int pastProfileId = pastProfileMeasure.getIntValue();
- Measure pastProfileVersionMeasure = getPreviousMeasure(project, CoreMetrics.PROFILE_VERSION);
- final int pastProfileVersion;
- // first analysis with versions
- if (pastProfileVersionMeasure == null) {
- pastProfileVersion = 1;
- } else {
- pastProfileVersion = pastProfileVersionMeasure.getIntValue();
- }
- String pastProfile = formatProfileDescription(pastProfileMeasure.getData(), pastProfileVersion);
-
- int currentProfileId = realProfile.getId();
- int currentProfileVersion = realProfile.getVersion();
- String currentProfile = formatProfileDescription(realProfile.getName(), currentProfileVersion);
-
- if ((pastProfileId != currentProfileId) || (pastProfileVersion != currentProfileVersion)) {
- // A different profile is used for this project or new version of same profile
- context.createEvent(project, currentProfile, currentProfile + " is used instead of " + pastProfile, Event.CATEGORY_PROFILE, null);
- }
- }
- }
-
- private static String formatProfileDescription(String name, int version) {
- return name + " version " + version;
- }
-
- private Measure getPreviousMeasure(Project project, Metric metric) {
- TimeMachineQuery query = new TimeMachineQuery(project)
- .setOnlyLastAnalysis(true)
- .setMetrics(metric);
- List<Measure> measures = timeMachine.getMeasures(query);
- if (measures.isEmpty()) {
- return null;
- }
- return measures.get(0);
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName();
- }
-}
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/description.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/description.html.erb
index 77931f40854..1d0fcb9c409 100644
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/description.html.erb
+++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/description.html.erb
@@ -25,7 +25,7 @@
<td><%= message('widget.description.profiles') -%>:</td>
<td><span id="resource_profile">
<% profiles.each_with_index do |profile, i| %>
- <%= Api::Utils.language_name(profile['language']) -%>: <%= link_to profile['name'], {:controller => '/rules_configuration', :action => 'index', :id => profile['id']}, :id => profile['language'] + '_profile_link' -%></span> (<%= message('widget.description.profile_version_x', :params => profile['version']) -%>)
+ <%= Api::Utils.language_name(profile['language']) -%>: <%= link_to profile['name'], {:controller => '/profiles', :action => 'show', :id => profile['id']}, :id => profile['language'] + '_profile_link' -%></span> (<%= message('widget.description.profile_version_x', :params => profile['version']) -%>)
<% if i < (profiles.size - 1) %>
<br/>
<% end %>
@@ -39,7 +39,7 @@
%>
<tr>
<td><%= message('widget.description.profile') -%>:</td>
- <td><span id="resource_profile"><%= link_to profile_measure.data, {:controller => '/rules_configuration', :action => 'index', :id => profile_measure.value.to_i}, :id => 'profile_link' -%></span> (<%= message('widget.description.profile_version_x', :params => format_measure('profile_version', :default => '1')) -%>)</td>
+ <td><span id="resource_profile"><%= link_to profile_measure.data, {:controller => '/profiles', :action => 'show', :id => profile_measure.value.to_i}, :id => 'profile_link' -%></span> (<%= message('widget.description.profile_version_x', :params => format_measure('profile_version', :default => '1')) -%>)</td>
</tr>
<% end
end %>
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileEventsSensorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileEventsSensorTest.java
deleted file mode 100644
index 41e50402699..00000000000
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileEventsSensorTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.plugins.core.sensors;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.batch.Event;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.batch.TimeMachine;
-import org.sonar.api.batch.TimeMachineQuery;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.internal.DefaultFileSystem;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.Project;
-import org.sonar.batch.rule.RulesProfileWrapper;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.*;
-
-public class ProfileEventsSensorTest {
-
- Project project;
- SensorContext context;
- FileSystem fs;
- RulesProfileWrapper wrapper;
- RulesProfile profile;
-
- @Before
- public void prepare() {
- project = mock(Project.class);
- context = mock(SensorContext.class);
-
- fs = new DefaultFileSystem().addLanguages("java");
- profile = mock(RulesProfile.class);
- when(profile.getLanguage()).thenReturn("java");
- wrapper = new RulesProfileWrapper(profile);
- }
-
- @Test
- public void shouldExecuteWhenProfileWithId() {
- when(profile.getId()).thenReturn(123);
- ProfileEventsSensor sensor = new ProfileEventsSensor(wrapper, null, fs);
-
- assertThat(sensor.shouldExecuteOnProject(project)).isTrue();
- verifyZeroInteractions(project);
- }
-
- @Test
- public void shouldNotExecuteIfProfileIsNotWrapper() {
- RulesProfile profile = mock(RulesProfile.class);
- when(profile.getId()).thenReturn(null);
- ProfileEventsSensor sensor = new ProfileEventsSensor(profile, null, fs);
-
- assertThat(sensor.shouldExecuteOnProject(project)).isFalse();
- verifyZeroInteractions(project);
- }
-
- @Test
- public void shouldDoNothingIfNoProfileChange() {
- mockProfileWithVersion(1);
- TimeMachine timeMachine = mockTM(22.0, "Foo", 1.0); // Same profile, same version
- ProfileEventsSensor sensor = new ProfileEventsSensor(wrapper, timeMachine, fs);
-
- sensor.analyse(project, context);
-
- verifyZeroInteractions(context);
- }
-
- @Test
- public void shouldCreateEventIfProfileChange() {
- mockProfileWithVersion(1);
- TimeMachine timeMachine = mockTM(21.0, "Bar", 1.0); // Different profile
- ProfileEventsSensor sensor = new ProfileEventsSensor(wrapper, timeMachine, fs);
-
- sensor.analyse(project, context);
-
- verify(context).createEvent(same(project),
- eq("Foo version 1"),
- eq("Foo version 1 is used instead of Bar version 1"),
- same(Event.CATEGORY_PROFILE), any(Date.class));
- }
-
- @Test
- public void shouldCreateEventIfProfileVersionChange() {
- mockProfileWithVersion(2);
- TimeMachine timeMachine = mockTM(22.0, "Foo", 1.0); // Same profile, different version
- ProfileEventsSensor sensor = new ProfileEventsSensor(wrapper, timeMachine, fs);
-
- sensor.analyse(project, context);
-
- verify(context).createEvent(same(project),
- eq("Foo version 2"),
- eq("Foo version 2 is used instead of Foo version 1"),
- same(Event.CATEGORY_PROFILE), any(Date.class));
- }
-
- @Test
- public void shouldNotCreateEventIfFirstAnalysis() {
- mockProfileWithVersion(2);
- TimeMachine timeMachine = mockTM(null, null);
- ProfileEventsSensor sensor = new ProfileEventsSensor(wrapper, timeMachine, fs);
-
- sensor.analyse(project, context);
-
- verifyZeroInteractions(context);
- }
-
- @Test
- public void shouldCreateEventIfFirstAnalysisWithVersionsAndVersionMoreThan1() {
- mockProfileWithVersion(2);
- TimeMachine timeMachine = mockTM(22.0, "Foo", null);
- ProfileEventsSensor sensor = new ProfileEventsSensor(wrapper, timeMachine, fs);
-
- sensor.analyse(project, context);
-
- verify(context).createEvent(same(project),
- eq("Foo version 2"),
- eq("Foo version 2 is used instead of Foo version 1"),
- same(Event.CATEGORY_PROFILE), any(Date.class));
- }
-
- private void mockProfileWithVersion(int version) {
- when(profile.getId()).thenReturn(22);
- when(profile.getName()).thenReturn("Foo");
- when(profile.getVersion()).thenReturn(version);
- }
-
- private TimeMachine mockTM(double profileId, String profileName, Double versionValue) {
- return mockTM(new Measure(CoreMetrics.PROFILE, profileId, profileName), versionValue == null ? null : new Measure(CoreMetrics.PROFILE_VERSION, versionValue));
- }
-
- private TimeMachine mockTM(Measure result1, Measure result2) {
- TimeMachine timeMachine = mock(TimeMachine.class);
-
- when(timeMachine.getMeasures(any(TimeMachineQuery.class)))
- .thenReturn(result1 == null ? Collections.<Measure>emptyList() : Arrays.asList(result1))
- .thenReturn(result2 == null ? Collections.<Measure>emptyList() : Arrays.asList(result2));
-
- return timeMachine;
- }
-}