diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2014-10-20 17:19:19 +0200 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2014-10-20 17:19:19 +0200 |
commit | de0f79313e6bb951db1b02a8138b5e8366884518 (patch) | |
tree | bcc379b2a711189cd52636926d20b800381dc4c6 | |
parent | ec0211e72ad2e817cc099daba64833797bfc17c6 (diff) | |
parent | 14bf33fa1c0f4ac920775ee2d2363337fa3769c0 (diff) | |
download | sonarqube-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
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. |