summaryrefslogtreecommitdiffstats
path: root/sonar-server/src/main
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2014-04-28 16:57:34 +0600
committerStephane Gamard <stephane.gamard@searchbox.com>2014-04-29 07:51:21 +0200
commitc182e12a80526320779adf36f1260af9b3eb83a1 (patch)
tree5a7d75d1933a37d44e3b5cfef2169af9b1dae31a /sonar-server/src/main
parent5eeeec7263cddbe9453895aef448f99f06222dbf (diff)
downloadsonarqube-c182e12a80526320779adf36f1260af9b3eb83a1.tar.gz
sonarqube-c182e12a80526320779adf36f1260af9b3eb83a1.zip
Component Viewer: duplications
Diffstat (limited to 'sonar-server/src/main')
-rw-r--r--sonar-server/src/main/coffee/component-viewer/coverage-popup.coffee16
-rw-r--r--sonar-server/src/main/coffee/component-viewer/duplication-popup.coffee36
-rw-r--r--sonar-server/src/main/coffee/component-viewer/main.coffee44
-rw-r--r--sonar-server/src/main/coffee/component-viewer/popup.coffee22
-rw-r--r--sonar-server/src/main/coffee/component-viewer/source.coffee42
-rw-r--r--sonar-server/src/main/hbs/component-viewer/duplicationPopup.hbs19
-rw-r--r--sonar-server/src/main/hbs/component-viewer/source.hbs31
-rw-r--r--sonar-server/src/main/less/component-viewer.less25
-rw-r--r--sonar-server/src/main/less/variables.less1
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb6
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>