diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2014-04-28 16:57:34 +0600 |
---|---|---|
committer | Stephane Gamard <stephane.gamard@searchbox.com> | 2014-04-29 07:51:21 +0200 |
commit | c182e12a80526320779adf36f1260af9b3eb83a1 (patch) | |
tree | 5a7d75d1933a37d44e3b5cfef2169af9b1dae31a /sonar-server/src/main | |
parent | 5eeeec7263cddbe9453895aef448f99f06222dbf (diff) | |
download | sonarqube-c182e12a80526320779adf36f1260af9b3eb83a1.tar.gz sonarqube-c182e12a80526320779adf36f1260af9b3eb83a1.zip |
Component Viewer: duplications
Diffstat (limited to 'sonar-server/src/main')
10 files changed, 221 insertions, 21 deletions
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 @@ +<div class="component-viewer-popup-section"> + <div class="component-viewer-popup-section-title"> + 2 duplications + </div> + <ul class="component-viewer-popup-list"> + <li> + <a data-key="org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/resources/ResourceTypeTree.java"> + <span>ResourceTypeTree.java</span> + </a> + </li> + <li> + <a data-key="org.codehaus.sonar:sonar-batch:src/main/java/org/sonar/batch/phases/PhaseExecutor.java"> + <span>PhaseExecutor.java</span> + </a> + </li> + </ul> +</div> + +<div class="component-viewer-popup-arrow"></div>
\ 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 @@ <th class="stat"></th> <th class="stat"></th> {{/if}} + {{#if settings.duplications}} + <th class="stat"></th> + {{/if}} <th class="stat settings-toggle"> <button class="button-clean js-toggle-settings"> <i class="icon-settings"></i></i> @@ -42,6 +45,9 @@ <th class="stat"></th> <th class="stat"></th> {{/if}} + {{#if settings.duplications}} + <th class="stat"></th> + {{/if}} <th class="stat settings-toggle"> <button class="button-clean js-toggle-measures"><i class="icon-list"></i></button> </th> @@ -93,8 +99,18 @@ {{/if}} </li> {{/if}} - <li class="component-viewer-measures-section"> - </li> + {{#if settings.duplications}} + <li class="component-viewer-measures-section brief"> + {{component.duplicationsMeasures}} + {{#if component.duplicationsMeasures}} + <dl> + {{#each component.duplicationsMeasures}} + <dt>{{t 'metric' key 'name'}}</dt><dd>{{frmt_val}}</dd> + {{/each}} + </dl> + {{/if}} + </li> + {{/if}} </ul> </th> </tr> @@ -105,6 +121,9 @@ <td class="stat coverage-tests"></td> <td class="stat coverage-conditions"></td> {{/if}} + {{#if settings.duplications}} + <td class="stat"></td> + {{/if}} <td class="stat lid"></td> <td class="line"></td> </tr> @@ -131,6 +150,14 @@ </td> {{/if}} + {{#if ../settings.duplications}} + <td class="stat duplications"> + {{#each duplications}} + <span class="duplication {{#if this}}duplication-exists{{/if}}"></span> + {{/each}} + </td> + {{/if}} + <td class="stat lid">{{lineNumber}}</td> <td class="line"><pre>{{{code}}}</pre></td> 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') -%>' }; </script> |