From c182e12a80526320779adf36f1260af9b3eb83a1 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Mon, 28 Apr 2014 16:57:34 +0600 Subject: [PATCH] Component Viewer: duplications --- .../component-viewer/coverage-popup.coffee | 16 ++----- .../component-viewer/duplication-popup.coffee | 36 +++++++++++++++ .../main/coffee/component-viewer/main.coffee | 44 ++++++++++++++++--- .../main/coffee/component-viewer/popup.coffee | 22 ++++++++++ .../coffee/component-viewer/source.coffee | 42 ++++++++++++++++++ .../hbs/component-viewer/duplicationPopup.hbs | 19 ++++++++ .../src/main/hbs/component-viewer/source.hbs | 31 ++++++++++++- .../src/main/less/component-viewer.less | 25 +++++++++++ sonar-server/src/main/less/variables.less | 1 + .../WEB-INF/app/views/issues/search.html.erb | 6 ++- 10 files changed, 221 insertions(+), 21 deletions(-) create mode 100644 sonar-server/src/main/coffee/component-viewer/duplication-popup.coffee create mode 100644 sonar-server/src/main/coffee/component-viewer/popup.coffee create mode 100644 sonar-server/src/main/hbs/component-viewer/duplicationPopup.hbs diff --git a/sonar-server/src/main/coffee/component-viewer/coverage-popup.coffee b/sonar-server/src/main/coffee/component-viewer/coverage-popup.coffee index 7623eebcd57..63d38c8b702 100644 --- a/sonar-server/src/main/coffee/component-viewer/coverage-popup.coffee +++ b/sonar-server/src/main/coffee/component-viewer/coverage-popup.coffee @@ -1,16 +1,17 @@ define [ 'backbone.marionette' 'templates/component-viewer' + 'component-viewer/popup' ], ( Marionette Templates + Popup ) -> $ = jQuery - class CoveragePopupView extends Marionette.ItemView - className: 'component-viewer-popup' + class CoveragePopupView extends Popup template: Templates['coveragePopup'] @@ -18,17 +19,6 @@ define [ 'click a[data-key]': 'goToFile' - onRender: -> - @$el.detach().appendTo $('body') - @$el.css - top: @options.triggerEl.offset().top - left: @options.triggerEl.offset().left + @options.triggerEl.outerWidth() - - $('body').on 'click.coverage-popup', => - $('body').off 'click.coverage-popup' - @close() - - goToFile: (e) -> key = $(e.currentTarget).data 'key' test = $(e.currentTarget).data 'test' diff --git a/sonar-server/src/main/coffee/component-viewer/duplication-popup.coffee b/sonar-server/src/main/coffee/component-viewer/duplication-popup.coffee new file mode 100644 index 00000000000..5a220687339 --- /dev/null +++ b/sonar-server/src/main/coffee/component-viewer/duplication-popup.coffee @@ -0,0 +1,36 @@ +define [ + 'backbone.marionette' + 'templates/component-viewer' + 'component-viewer/popup' +], ( + Marionette + Templates + Popup +) -> + + $ = jQuery + + + class DuplicationPopupView extends Popup + template: Templates['duplicationPopup'] + + + events: + 'click a[data-key]': 'goToFile' + + + goToFile: (e) -> + key = $(e.currentTarget).data 'key' + @options.main.addTransition key, 'duplication', [ + { + key: 'org.codehaus.sonar:sonar-plugin-api:src/test/java/org/sonar/api/resources/ResourceTypeTree.java' + name: 'ResourceTypeTree.java' + active: true + } + { + key: 'org.codehaus.sonar:sonar-batch:src/main/java/org/sonar/batch/phases/PhaseExecutor.java' + name: 'PhaseExecutor.java' + active: false + } + ], [] + diff --git a/sonar-server/src/main/coffee/component-viewer/main.coffee b/sonar-server/src/main/coffee/component-viewer/main.coffee index 5601a7b88d1..0f540618849 100644 --- a/sonar-server/src/main/coffee/component-viewer/main.coffee +++ b/sonar-server/src/main/coffee/component-viewer/main.coffee @@ -25,6 +25,8 @@ define [ ISSUES_METRIC_LIST = 'blocker_violations,critical_violations,major_violations,minor_violations,info_violations' + DUPLICATIONS_METRIC_LIST = 'duplicated_lines_density,duplicated_blocks,duplicated_files,duplicated_lines' + class ComponentViewer extends Marionette.Layout @@ -52,7 +54,7 @@ define [ @settings = new Backbone.Model issues: false coverage: false - duplications: false + duplications: true scm: false workspace: false @@ -79,6 +81,10 @@ define [ $.get API_RESOURCES, resource: key, metrics: ISSUES_METRIC_LIST + requestComponentDuplications: (key) -> + $.get API_RESOURCES, resource: key, metrics: DUPLICATIONS_METRIC_LIST + + requestSource: (key) -> $.get API_SOURCES, resource: key, (data) => @source.set source: data[0] @@ -87,15 +93,15 @@ define [ extractCoverage: (data) -> toObj = (d) -> q = {} - d.split(';').forEach (item) -> + d?.split(';').forEach (item) -> tokens = item.split '=' q[tokens[0]] = tokens[1] q msr = data[0].msr - coverage = toObj _.findWhere(msr, key: 'coverage_line_hits_data').data - coverageConditions = toObj _.findWhere(msr, key: 'covered_conditions_by_line').data - conditions = toObj _.findWhere(msr, key: 'conditions_by_line').data + coverage = toObj _.findWhere(msr, key: 'coverage_line_hits_data')?.data + coverageConditions = toObj _.findWhere(msr, key: 'covered_conditions_by_line')?.data + conditions = toObj _.findWhere(msr, key: 'conditions_by_line')?.data @source.set coverage: coverage coverageConditions: coverageConditions @@ -105,6 +111,18 @@ define [ @component.set 'coverageMeasures', coverageMeasures + extractDuplications: (data) -> + @source.set + duplications: [ + { from: 18, count: 33 } + { from: 24, count: 23 } + { from: 62, count: 33 } + ] + duplicationsMeasures = _.sortBy data[0].msr, (item) -> -(item.key == 'duplicated_lines_density') + console.log data + @component.set 'duplicationsMeasures', duplicationsMeasures + + extractIssues: (data) -> issuesMeasures = {} data[0].msr.forEach (q) -> @@ -127,6 +145,7 @@ define [ model.set 'component': @component.toJSON() @render() if @settings.get('coverage') then @showCoverage() else @hideCoverage() + if @settings.get('duplications') then @showDuplications() else @hideDuplications() showCoverage: -> @@ -172,6 +191,21 @@ define [ @sourceView.render() + showDuplications: -> + @settings.set 'duplications', true + unless @source.has 'duplications' + @requestComponentDuplications(@key).done (data) => + @extractDuplications data + @sourceView.render() + else + @sourceView.render() + + + hideDuplications: -> + @settings.set 'duplications', false + @sourceView.render() + + addTransition: (key, transition, optionsForCurrent, options) -> if optionsForCurrent? last = @workspace.at(@workspace.length - 1) diff --git a/sonar-server/src/main/coffee/component-viewer/popup.coffee b/sonar-server/src/main/coffee/component-viewer/popup.coffee new file mode 100644 index 00000000000..bd806802b06 --- /dev/null +++ b/sonar-server/src/main/coffee/component-viewer/popup.coffee @@ -0,0 +1,22 @@ +define [ + 'backbone.marionette' +], ( + Marionette +) -> + + $ = jQuery + + + class CoveragePopupView extends Marionette.ItemView + className: 'component-viewer-popup' + + + onRender: -> + @$el.detach().appendTo $('body') + @$el.css + top: @options.triggerEl.offset().top + left: @options.triggerEl.offset().left + @options.triggerEl.outerWidth() + + $('body').on 'click.coverage-popup', => + $('body').off 'click.coverage-popup' + @close() \ No newline at end of file diff --git a/sonar-server/src/main/coffee/component-viewer/source.coffee b/sonar-server/src/main/coffee/component-viewer/source.coffee index 74b37753166..e54ec45efd8 100644 --- a/sonar-server/src/main/coffee/component-viewer/source.coffee +++ b/sonar-server/src/main/coffee/component-viewer/source.coffee @@ -2,6 +2,7 @@ define [ 'backbone.marionette' 'templates/component-viewer' 'component-viewer/coverage-popup' + 'component-viewer/duplication-popup' 'issues/issue-view' 'issues/models/issue' 'common/handlebars-extensions' @@ -9,6 +10,7 @@ define [ Marionette Templates CoveragePopupView + DuplicationPopupView IssueView Issue ) -> @@ -24,9 +26,14 @@ define [ 'click .js-toggle-settings': 'toggleSettings' 'click .js-toggle-measures': 'toggleMeasures' 'change #source-coverage': 'toggleCoverage' + 'change #source-duplications': 'toggleDuplications' 'change #source-workspace': 'toggleWorkspace' 'click .coverage-tests': 'showCoveragePopup' + 'click .duplication-exists': 'showDuplicationPopup' + 'mouseenter .duplication-exists': 'duplicationMouseEnter' + 'mouseleave .duplication-exists': 'duplicationMouseLeave' + onRender: -> @delegateEvents() @@ -64,6 +71,12 @@ define [ if active then @options.main.showCoverage() else @options.main.hideCoverage() + toggleDuplications: (e) -> + active = $(e.currentTarget).is ':checked' + @showSettings = true + if active then @options.main.showDuplications() else @options.main.hideDuplications() + + toggleWorkspace: (e) -> active = $(e.currentTarget).is ':checked' @showSettings = true @@ -79,11 +92,36 @@ define [ popup.render() + showDuplicationPopup: (e) -> + e.stopPropagation() + $('body').click() + popup = new DuplicationPopupView + triggerEl: $(e.currentTarget) + main: @options.main + popup.render() + + + duplicationMouseEnter: (e) -> + @toggleDuplicationHover e, true + + + duplicationMouseLeave: (e) -> + @toggleDuplicationHover e, false + + + toggleDuplicationHover: (e, add) -> + bar = $(e.currentTarget) + index = bar.parent().children('.duplication').index bar + @$('.duplications').each -> + $(".duplication", @).eq(index).filter('.duplication-exists').toggleClass 'duplication-hover', add + + prepareSource: -> source = @model.get 'source' coverage = @model.get 'coverage' coverageConditions = @model.get 'coverageConditions' conditions = @model.get 'conditions' + duplications = @model.get('duplications') || [] _.map source, (code, line) -> lineCoverage = coverage? && coverage[line]? && coverage[line] lineCoverage = +lineCoverage if _.isString lineCoverage @@ -103,6 +141,9 @@ define [ lineCoverageConditionsStatus = 'orange' if lineCoverageConditions > 0 && lineCoverageConditions < lineConditions lineCoverageConditionsStatus = 'green' if lineCoverageConditions == lineConditions + lineDuplications = duplications.map (d) -> + d.from <= line && (d.from + d.count) > line + lineNumber: line code: code coverage: lineCoverage @@ -110,6 +151,7 @@ define [ coverageConditions: lineCoverageConditions conditions: lineConditions coverageConditionsStatus: lineCoverageConditionsStatus || lineCoverageStatus + duplications: lineDuplications serializeData: -> diff --git a/sonar-server/src/main/hbs/component-viewer/duplicationPopup.hbs b/sonar-server/src/main/hbs/component-viewer/duplicationPopup.hbs new file mode 100644 index 00000000000..3be9afb0a5a --- /dev/null +++ b/sonar-server/src/main/hbs/component-viewer/duplicationPopup.hbs @@ -0,0 +1,19 @@ +
+
+ 2 duplications +
+ +
+ +
\ No newline at end of file diff --git a/sonar-server/src/main/hbs/component-viewer/source.hbs b/sonar-server/src/main/hbs/component-viewer/source.hbs index c6372ef5da1..ba11ec0cf52 100644 --- a/sonar-server/src/main/hbs/component-viewer/source.hbs +++ b/sonar-server/src/main/hbs/component-viewer/source.hbs @@ -5,6 +5,9 @@ {{/if}} + {{#if settings.duplications}} + + {{/if}} @@ -93,8 +99,18 @@ {{/if}} {{/if}} -
  • -
  • + {{#if settings.duplications}} +
  • + {{component.duplicationsMeasures}} + {{#if component.duplicationsMeasures}} +
    + {{#each component.duplicationsMeasures}} +
    {{t 'metric' key 'name'}}
    {{frmt_val}}
    + {{/each}} +
    + {{/if}} +
  • + {{/if}} @@ -105,6 +121,9 @@ {{/if}} + {{#if settings.duplications}} + + {{/if}} @@ -131,6 +150,14 @@ {{/if}} + {{#if ../settings.duplications}} + + {{#each duplications}} + + {{/each}} + + {{/if}} + {{lineNumber}}
    {{{code}}}
    diff --git a/sonar-server/src/main/less/component-viewer.less b/sonar-server/src/main/less/component-viewer.less index 6f1d21d59e2..7f2f9979911 100644 --- a/sonar-server/src/main/less/component-viewer.less +++ b/sonar-server/src/main/less/component-viewer.less @@ -124,6 +124,7 @@ font-size: 11px; text-align: right; cursor: default; + white-space: nowrap; } .sources2 .lid { @@ -136,6 +137,30 @@ cursor: pointer; } + .sources2 .duplications { + padding-top: 0; + padding-bottom: 0; + font-size: 0; + + .duplication { + display: inline-block; + vertical-align: top; + .size(5px, 100%); + } + + .duplication + .duplication { margin-left: 2px; } + + .duplication-exists { + background-color: @lightOrange; + cursor: pointer; + .trans; + } + + .duplication-hover { + background-color: darken(@lightOrange, 10%); + } + } + .sources2 .measures { padding: 4px 5px; border-left: 1px solid @barBorderColor; diff --git a/sonar-server/src/main/less/variables.less b/sonar-server/src/main/less/variables.less index 659091e4ba4..ea62c4aaba9 100644 --- a/sonar-server/src/main/less/variables.less +++ b/sonar-server/src/main/less/variables.less @@ -24,6 +24,7 @@ @green: #85bb43; @yellow: #fede06; @orange: #f90; +@lightOrange: #f3ca8e; @purple: #9139d4; @darkBlue: darken(@blue, 20%); diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb index d09c9d319c3..758be6eae54 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb @@ -238,6 +238,10 @@ 'metric.file_complexity_distribution.name': '<%= escape_javascript message('metric.file_complexity_distribution.name') -%>', 'metric.coverage.name': '<%= escape_javascript message('metric.coverage.name') -%>', 'metric.line_coverage.name': '<%= escape_javascript message('metric.line_coverage.name') -%>', - 'metric.branch_coverage.name': '<%= escape_javascript message('metric.branch_coverage.name') -%>' + 'metric.branch_coverage.name': '<%= escape_javascript message('metric.branch_coverage.name') -%>', + 'metric.duplicated_blocks.name': '<%= escape_javascript message('metric.duplicated_blocks.name') -%>', + 'metric.duplicated_files.name': '<%= escape_javascript message('metric.duplicated_files.name') -%>', + 'metric.duplicated_lines.name': '<%= escape_javascript message('metric.duplicated_lines.name') -%>', + 'metric.duplicated_lines_density.name': '<%= escape_javascript message('metric.duplicated_lines_density.name') -%>' }; -- 2.39.5