aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-10-20 17:19:19 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2014-10-20 17:19:19 +0200
commitde0f79313e6bb951db1b02a8138b5e8366884518 (patch)
treebcc379b2a711189cd52636926d20b800381dc4c6
parentec0211e72ad2e817cc099daba64833797bfc17c6 (diff)
parent14bf33fa1c0f4ac920775ee2d2363337fa3769c0 (diff)
downloadsonarqube-de0f79313e6bb951db1b02a8138b5e8366884518.tar.gz
sonarqube-de0f79313e6bb951db1b02a8138b5e8366884518.zip
Merge remote-tracking branch 'origin/branch-4.5'
Conflicts: sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
-rw-r--r--server/sonar-web/src/main/coffee/coding-rules/views/coding-rules-detail-view.coffee2
-rw-r--r--server/sonar-web/src/main/coffee/component-viewer/main.coffee9
-rw-r--r--server/sonar-web/src/main/coffee/component-viewer/source.coffee13
-rw-r--r--server/sonar-web/src/main/hbs/component-viewer/cw-source.hbs8
-rw-r--r--server/sonar-web/src/main/less/icons.less4
-rw-r--r--server/sonar-web/src/main/less/select-list.less2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java31
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationUtils.java48
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/DuplicationPersister.java26
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java8
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java3
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties1
12 files changed, 115 insertions, 40 deletions
diff --git a/server/sonar-web/src/main/coffee/coding-rules/views/coding-rules-detail-view.coffee b/server/sonar-web/src/main/coffee/coding-rules/views/coding-rules-detail-view.coffee
index 16ba0bb7925..7a10db2512f 100644
--- a/server/sonar-web/src/main/coffee/coding-rules/views/coding-rules-detail-view.coffee
+++ b/server/sonar-web/src/main/coffee/coding-rules/views/coding-rules-detail-view.coffee
@@ -335,5 +335,5 @@ define [
isEditable: (@options.app.canWrite and (isManual or isCustom))
qualityProfilesVisible: qualityProfilesVisible
subcharacteristic: @options.app.getSubcharacteristicName(@model.get 'debtSubChar')
- createdAt: new Date(@model.get 'createdAt')
+ createdAt: moment(@model.get 'createdAt').toDate()
allTags: _.union @model.get('sysTags'), @model.get('tags')
diff --git a/server/sonar-web/src/main/coffee/component-viewer/main.coffee b/server/sonar-web/src/main/coffee/component-viewer/main.coffee
index e6da45caa2f..5ba64c236a0 100644
--- a/server/sonar-web/src/main/coffee/component-viewer/main.coffee
+++ b/server/sonar-web/src/main/coffee/component-viewer/main.coffee
@@ -65,6 +65,8 @@ define [
SCROLL_OFFSET = 10
+ LINES_LIMIT = 3000
+
class ComponentViewer extends utils.mixOf Marionette.Layout, IssuesMixin, CoverageMixin, DuplicationsMixin, SCMMixin
@@ -201,10 +203,15 @@ define [
$.get API_MEASURES, data, (data) =>
measuresList = data[0].msr || []
measures = @component.get 'measures'
+ lines = null
measuresList.forEach (m) ->
measures[m.key] = m.frmt_val || m.data
+ lines = m.val if m.key == 'ncloc'
@component.set 'measures', measures
- @augmentWithNclocData()
+ if lines < LINES_LIMIT
+ @augmentWithNclocData()
+ else
+ delete measures['ncloc_data']
requestTrends: (key, period) ->
diff --git a/server/sonar-web/src/main/coffee/component-viewer/source.coffee b/server/sonar-web/src/main/coffee/component-viewer/source.coffee
index bad93f7bc93..423a555c3a3 100644
--- a/server/sonar-web/src/main/coffee/component-viewer/source.coffee
+++ b/server/sonar-web/src/main/coffee/component-viewer/source.coffee
@@ -22,6 +22,7 @@ define [
$ = jQuery
API_COVERAGE_TESTS = "#{baseUrl}/api/tests/test_cases"
+ LINES_LIMIT = 3000
ISSUES_LIMIT = 100
@@ -91,6 +92,7 @@ define [
$(expand).insertBefore rows.first()
lines = _.size @model.get 'source'
+ lines = Math.min lines, LINES_LIMIT
lastShown = rows.last().data('line-number')
if lastShown < lines
expand = @expandTemplate from: lastShown, to: lines, settings: @options.main.settings.toJSON()
@@ -274,16 +276,17 @@ define [
source.forEach (sourceLine) =>
show = false
line = sourceLine.lineNumber
- @showBlocks.forEach (block) ->
- show = true if block.from <= line && block.to >= line
- _.extend sourceLine, show: show
+ if line <= LINES_LIMIT
+ @showBlocks.forEach (block) ->
+ show = true if block.from <= line && block.to >= line
+ _.extend sourceLine, show: show
source
prepareSource: ->
source = @model.get 'formattedSource'
if source?
- @augmentWithShow source
+ _.first @augmentWithShow(source), LINES_LIMIT
getStatColumnsCount: ->
@@ -313,3 +316,5 @@ define [
showZeroLine: @showZeroLine()
issuesLimit: ISSUES_LIMIT
issuesLimitReached: @model.get('activeIssues')?.length > ISSUES_LIMIT
+ linesLimit: LINES_LIMIT
+ linesLimitReached: _.size(@model.get 'source') > LINES_LIMIT
diff --git a/server/sonar-web/src/main/hbs/component-viewer/cw-source.hbs b/server/sonar-web/src/main/hbs/component-viewer/cw-source.hbs
index 96f27fd2125..33c9134e6e4 100644
--- a/server/sonar-web/src/main/hbs/component-viewer/cw-source.hbs
+++ b/server/sonar-web/src/main/hbs/component-viewer/cw-source.hbs
@@ -4,14 +4,18 @@
{{else}}
- {{#if state.duplicationsInDeletedFiles}}
- <p class="marginbottom10 js-duplications-in-deleted-files">{{t 'duplications.dups_found_on_deleted_resource'}}</p>
+ {{#if linesLimitReached}}
+ <p class="message-alert marginbottom10">{{tp 'component_viewer.lines_limit_reached' linesLimit}}</p>
{{/if}}
{{#if issuesLimitReached}}
<p class="message-alert marginbottom10">{{tp 'component_viewer.issues_limit_reached' issuesLimit}}</p>
{{/if}}
+ {{#if state.duplicationsInDeletedFiles}}
+ <p class="marginbottom10 js-duplications-in-deleted-files">{{t 'duplications.dups_found_on_deleted_resource'}}</p>
+ {{/if}}
+
<table class="code">
{{#if showZeroLine}}
<tr class="row row-hidden" data-line-number="0" id="{{uid}}-0">
diff --git a/server/sonar-web/src/main/less/icons.less b/server/sonar-web/src/main/less/icons.less
index fa174f8b19b..1212069bb00 100644
--- a/server/sonar-web/src/main/less/icons.less
+++ b/server/sonar-web/src/main/less/icons.less
@@ -271,7 +271,9 @@ a[class^="icon-"], a[class*=" icon-"] {
&:after {
content: "\e60d";
position: absolute;
- top: 0; left: 0;
+// top: 0;
+ left: 0;
+ margin-top: 2px;
}
&.icon-checkbox-single:after { content: "\e60e"; }
diff --git a/server/sonar-web/src/main/less/select-list.less b/server/sonar-web/src/main/less/select-list.less
index d608d665000..e03bd93ba59 100644
--- a/server/sonar-web/src/main/less/select-list.less
+++ b/server/sonar-web/src/main/less/select-list.less
@@ -20,7 +20,7 @@
}
.select-list-list-container.loading .select-list-list {
- display: none;
+ visibility: hidden;
}
.select-list-list-container-readonly {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
index eb8174abb0d..fe7cdd7f57c 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
@@ -25,7 +25,9 @@ import com.google.common.collect.Lists;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.batch.Event;
import org.sonar.api.batch.SonarIndex;
+import org.sonar.api.batch.sensor.duplication.DuplicationGroup;
import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
import org.sonar.api.measures.MeasuresFilters;
@@ -36,10 +38,14 @@ import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.SonarException;
import org.sonar.api.violations.ViolationQuery;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.duplication.DuplicationUtils;
import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.core.measure.MeasurementFilters;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
@@ -57,17 +63,19 @@ public class DefaultDecoratorContext implements DecoratorContext {
private ListMultimap<String, Measure> measuresByMetric = ArrayListMultimap.create();
private MeasureCache measureCache;
private MetricFinder metricFinder;
+ private final DuplicationCache duplicationCache;
public DefaultDecoratorContext(Resource resource,
SonarIndex index,
List<DecoratorContext> childrenContexts,
- MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder) {
+ MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder, DuplicationCache duplicationCache) {
this.sonarIndex = index;
this.resource = resource;
this.childrenContexts = childrenContexts;
this.measurementFilters = measurementFilters;
this.measureCache = measureCache;
this.metricFinder = metricFinder;
+ this.duplicationCache = duplicationCache;
}
public void init() {
@@ -107,14 +115,31 @@ public class DefaultDecoratorContext implements DecoratorContext {
public <M> M getMeasures(MeasuresFilter<M> filter) {
Collection<Measure> unfiltered;
if (filter instanceof MeasuresFilters.MetricFilter) {
- // optimization
- unfiltered = measuresByMetric.get(((MeasuresFilters.MetricFilter<M>) filter).filterOnMetricKey());
+ unfiltered = getMeasuresOfASingleMetric(filter);
} else {
unfiltered = measuresByMetric.values();
}
return filter.filter(unfiltered);
}
+ private <M> Collection<Measure> getMeasuresOfASingleMetric(MeasuresFilter<M> filter) {
+ Collection<Measure> unfiltered;
+ String metricKey = ((MeasuresFilters.MetricFilter<M>) filter).filterOnMetricKey();
+ if (CoreMetrics.DUPLICATIONS_DATA_KEY.equals(metricKey)) {
+ // Hack for SONAR-5765
+ List<DuplicationGroup> group = duplicationCache.byComponent(resource.getEffectiveKey());
+ if (group != null) {
+ unfiltered = Arrays.asList(new Measure(CoreMetrics.DUPLICATIONS_DATA, DuplicationUtils.toXml(group)));
+ } else {
+ unfiltered = Collections.<Measure>emptyList();
+ }
+ } else {
+ // optimization
+ unfiltered = measuresByMetric.get(metricKey);
+ }
+ return unfiltered;
+ }
+
@Override
public Measure getMeasure(Metric metric) {
return getMeasures(MeasuresFilters.metric(metric));
diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationUtils.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationUtils.java
new file mode 100644
index 00000000000..f99aa02a023
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationUtils.java
@@ -0,0 +1,48 @@
+/*
+ * 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.batch.duplication;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.sonar.api.batch.sensor.duplication.DuplicationGroup;
+
+public class DuplicationUtils {
+
+ public static String toXml(Iterable<DuplicationGroup> duplications) {
+ StringBuilder xml = new StringBuilder();
+ xml.append("<duplications>");
+ for (DuplicationGroup duplication : duplications) {
+ xml.append("<g>");
+ toXml(xml, duplication.originBlock());
+ for (DuplicationGroup.Block part : duplication.duplicates()) {
+ toXml(xml, part);
+ }
+ xml.append("</g>");
+ }
+ xml.append("</duplications>");
+ return xml.toString();
+ }
+
+ private static void toXml(StringBuilder xml, DuplicationGroup.Block part) {
+ xml.append("<b s=\"").append(part.startLine())
+ .append("\" l=\"").append(part.length())
+ .append("\" r=\"").append(StringEscapeUtils.escapeXml(part.resourceKey()))
+ .append("\"/>");
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DuplicationPersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/DuplicationPersister.java
index 9461d46dfd7..4e5ebce1ef1 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/DuplicationPersister.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/DuplicationPersister.java
@@ -19,7 +19,6 @@
*/
package org.sonar.batch.index;
-import org.apache.commons.lang.StringEscapeUtils;
import org.sonar.api.batch.sensor.duplication.DuplicationGroup;
import org.sonar.api.database.model.MeasureMapper;
import org.sonar.api.database.model.MeasureModel;
@@ -30,6 +29,7 @@ import org.sonar.api.measures.PersistenceMode;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.RuleFinder;
import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.duplication.DuplicationUtils;
import org.sonar.batch.index.Cache.Entry;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
@@ -64,7 +64,7 @@ public final class DuplicationPersister implements ScanPersister {
org.sonar.api.measures.Metric duplicationMetricWithId = metricFinder.findByKey(CoreMetrics.DUPLICATIONS_DATA_KEY);
for (Entry<List<DuplicationGroup>> entry : duplicationCache.entries()) {
String effectiveKey = entry.key()[0].toString();
- Measure measure = new Measure(duplicationMetricWithId, toXml(entry.value())).setPersistenceMode(PersistenceMode.DATABASE);
+ Measure measure = new Measure(duplicationMetricWithId, DuplicationUtils.toXml(entry.value())).setPersistenceMode(PersistenceMode.DATABASE);
Resource resource = resourceCache.get(effectiveKey);
if (MeasurePersister.shouldPersistMeasure(resource, measure)) {
@@ -82,26 +82,4 @@ public final class DuplicationPersister implements ScanPersister {
}
}
- private static String toXml(Iterable<DuplicationGroup> duplications) {
- StringBuilder xml = new StringBuilder();
- xml.append("<duplications>");
- for (DuplicationGroup duplication : duplications) {
- xml.append("<g>");
- toXml(xml, duplication.originBlock());
- for (DuplicationGroup.Block part : duplication.duplicates()) {
- toXml(xml, part);
- }
- xml.append("</g>");
- }
- xml.append("</duplications>");
- return xml.toString();
- }
-
- private static void toXml(StringBuilder xml, DuplicationGroup.Block part) {
- xml.append("<b s=\"").append(part.startLine())
- .append("\" l=\"").append(part.length())
- .append("\" r=\"").append(StringEscapeUtils.escapeXml(part.resourceKey()))
- .append("\"/>");
- }
-
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java
index c6aa4ac8a79..b867e0fc010 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java
@@ -32,6 +32,7 @@ import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.DecoratorsSelector;
import org.sonar.batch.DefaultDecoratorContext;
+import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.core.measure.MeasurementFilters;
@@ -48,11 +49,14 @@ public class DecoratorsExecutor implements BatchComponent {
private MeasurementFilters measurementFilters;
private MeasureCache measureCache;
private MetricFinder metricFinder;
+ private final DuplicationCache duplicationCache;
public DecoratorsExecutor(BatchExtensionDictionnary batchExtDictionnary,
- Project project, SonarIndex index, EventBus eventBus, MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder) {
+ Project project, SonarIndex index, EventBus eventBus, MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder,
+ DuplicationCache duplicationCache) {
this.measureCache = measureCache;
this.metricFinder = metricFinder;
+ this.duplicationCache = duplicationCache;
this.decoratorsSelector = new DecoratorsSelector(batchExtDictionnary);
this.index = index;
this.eventBus = eventBus;
@@ -75,7 +79,7 @@ public class DecoratorsExecutor implements BatchComponent {
childrenContexts.add(childContext.end());
}
- DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, measurementFilters, measureCache, metricFinder);
+ DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, measurementFilters, measureCache, metricFinder, duplicationCache);
context.init();
if (executeDecorators) {
for (Decorator decorator : decorators) {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java b/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java
index 12d35f08b4d..3516ab363fb 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java
@@ -30,6 +30,7 @@ import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.DefaultDecoratorContext;
+import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.core.measure.MeasurementFilters;
@@ -66,7 +67,7 @@ public class DecoratorsExecutorTest {
doThrow(new SonarException()).when(decorator).decorate(any(Resource.class), any(DecoratorContext.class));
DecoratorsExecutor executor = new DecoratorsExecutor(mock(BatchExtensionDictionnary.class), new Project("key"), mock(SonarIndex.class),
- mock(EventBus.class), mock(MeasurementFilters.class), mock(MeasureCache.class), mock(MetricFinder.class));
+ mock(EventBus.class), mock(MeasurementFilters.class), mock(MeasureCache.class), mock(MetricFinder.class), mock(DuplicationCache.class));
try {
executor.executeDecorator(decorator, mock(DefaultDecoratorContext.class), File.create("src/org/foo/Bar.java", "org/foo/Bar.java", null, false));
fail("Exception has not been thrown");
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
index 55ebb3441c7..1bb662b5f33 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -2722,6 +2722,7 @@ component_viewer.more_actions=More Actions
component_viewer.new_window=Open in New Window
component_viewer.get_permalink=Get Permalink
component_viewer.covered_lines=Covered Lines
+component_viewer.lines_limit_reached=For performance reasons, only the {0} first lines will be displayed.
component_viewer.issues_limit_reached=For usability reasons, only the {0} first issues will be fully displayed. Remaining issues will simply be underlined.
component_viewer.issues_limit_reached_tooltip={0}\n\nRefine your filter to be able to see the details of this issue.
component_viewer.cannot_show=We're sorry, but something went wrong. Please try back in a few minutes and contact support if the problem persists.